前后端分离,springboot实现token拦截器,注解放行restfulAPI、白名单过滤

放行注解定义

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcludeInterceptor {
}

白名单注解定义

/**

  • @des 白名单验证注解
  • @author wxg
  • @date 2020年4月7日
    */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface VerifWhiteList {
    }

登录拦截器,接口放行、白名单、验权

/**

  • @author wxg

  • @date 2020年3月23日

  • @des 登录拦截器
    */
    @Component
    public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Value(" s p r i n g . p r o f i l e s . a c t i v e " ) p r i v a t e S t r i n g a c t i v e ; @ V a l u e ( " {spring.profiles.active}") private String active; @Value(" spring.profiles.active")privateStringactive;@Value("{acount.visitors.ips}")
    private String visitorsIps;
    @Value(" r e d i s . k e y . t o k e n . p r e f i x " ) p r i v a t e S t r i n g t o k e n R e d i s K e y P r e f i x ; @ V a l u e ( " {redis.key.token.prefix}") private String tokenRedisKeyPrefix; @Value(" redis.key.token.prefix")privateStringtokenRedisKeyPrefix;@Value("{redis.key.account.prefix}")
    private String redisAccountPrefix;
    @Autowired
    private RedisMapper redisMapper;
    @Resource
    private AccountMapper accountMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (handler instanceof HandlerMethod) {
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Method method = handlerMethod.getMethod();
    // 接口放行注解
    ExcludeInterceptor excludeInterceptor = method.getAnnotation(ExcludeInterceptor.class);
    // 无需验证
    if (null != excludeInterceptor) {
    String ip = IpUtil.getIpAddress(request);
    // 接口放行时,如果存在验证白名单验证注解 @VerifWhiteList,验证白名单
    VerifWhiteList verifWhiteList = method.getAnnotation(VerifWhiteList.class);
    if(null != verifWhiteList) {
    // 1、拦截,不满足白名单
    if (!visitorsIps.contains(ip)) {
    return false;
    }
    }
    return super.preHandle(request, response, handler);
    }
    LoginUser loginUser = getUser(request, response);
    if (null == loginUser) {
    return false;
    }
    UserInfoContext.setUser(loginUser);
    }
    return super.preHandle(request, response, handler);
    }

    private LoginUser getUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 需要增加信息字段可通过此处进行扩充
    LoginUser loginUser = new LoginUser();
    // 开发环境, 模拟用户
    if (active.equals(DeployConstant.DEV)) {
    loginUser.setAccountId(“123456”);
    loginUser.setLoginName(“wxg”);
    loginUser.setUserId(“1”);
    loginUser.setWorker(“王旭光”);
    loginUser.setIp(“127.0.0.1”);
    } else {
    String token = request.getHeader(“token”);
    // header中无token
    if (StringUtils.isEmpty(token)) {
    printJson(response, Message.Code.HEADER_TOKEN_EXIST);
    return null;
    }

         /** 从redis中获取用户名,验证token有效性 **/
         String userName = redisMapper.get(tokenRedisKeyPrefix + token);
         // token 无效
         if (StringUtils.isEmpty(userName)) {
             printJson(response, Message.Code.TOKEN_NOT_EXIST);
             return null;
         } else {
             // token续命2个小时
             redisMapper.expire(tokenRedisKeyPrefix + token, 43200);
             /** 根据用户名,获取登录用户必要信息 **/
             // 先从redis中获取是否有用户基本信息
             String loginUserStr = redisMapper.get(redisAccountPrefix + userName);
    
             if (StringUtils.isEmpty(loginUserStr)) {
                 List loginUsers = accountMapper.selectLoginInfoByLoginName(userName);
                 if (null != loginUsers && loginUsers.size() == 1) {
                     loginUser = loginUsers.get(0);
                     redisMapper.set(redisAccountPrefix + userName, JSONObject.toJSONString(loginUser),1800);
                 } else {
                     printJson(response, Message.Code.TOKEN_NOT_EXIST);
                     return null;
                 }
             }
             // redis中已有用户信息
             else {
                 loginUser = JSONObject.parseObject(loginUserStr, LoginUser.class);
             }
             // 获取ip
             loginUser.setIp(IpUtil.getIpAddress(request));
    
         }
     }
    
     return loginUser;
    

    }

    private static void printJson(HttpServletResponse response, String code) {
    String content = JSON.toJSONString(new MessageBuilder.Builder()
    .setStatus(Message.Code.STATUS_ERROR)
    .setErrorCode(code).builder());
    printContent(response, content);
    }

    private static void printContent(HttpServletResponse response, String content) {
    try {
    response.reset();
    response.setContentType(“application/json”);
    response.setHeader(“Cache-Control”, “no-store”);
    response.setCharacterEncoding(“UTF-8”);
    PrintWriter pw = response.getWriter();
    pw.write(content);
    pw.flush();
    pw.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

登录参数解析器

/**

  • @author wxg

  • @date 2020年3月23日

  • @des 登录参数解析器
    */
    @Component
    public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
    Class clazz = parameter.getParameterType();
    return clazz== LoginUser.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
    NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    return UserInfoContext.getUser();
    }
    }

登录用户model

/**

  • @author wxg
  • @date 2020年3月23日
  • @des 登录用户信息
    /
    @Data
    public class LoginUser {
    /
    * 账号id /
    private String accountId;
    /
    登录名 /
    private String loginName;
    /
    用户id /
    private String userId;
    /
    用户名 /
    private String worker;
    /
    ip **/
    private String ip;
    }

运用ThreadLocal存储登录用户信息

/**

  • @author wxg

  • @date 2020年3月23日

  • @des ThreadLocal工具类 :UserInfoContext
    /
    public class UserInfoContext {
    /
    *

    • 登录用户上下文存储
      */
      private static final ThreadLocal userHolder = new ThreadLocal<>();

    public static void setUser(LoginUser loginUser) {
    userHolder.set(loginUser);
    }

    public static LoginUser getUser() {
    return userHolder.get();
    }

}

Controller层应用案例

/**
* 跨服务注册,无需token验权,白名单过滤
*
* @param accountUserAddReq
* @param httpServletRequest
* @return
*/
@PostMapping("/accountRegister")
@ExcludeInterceptor
@VerifWhiteList
public String accountRegister(@RequestBody AccountUserAddReq accountUserAddReq, HttpServletRequest httpServletRequest) {
return JSONObject.toJSONString(accountAddService.lanDoAdd(accountUserAddReq));
}

你可能感兴趣的:(分离,token,拦截器,spring,java,spring,boot)