springboot登录拦截方法

controller代码

@RestController
@RequestMapping("/user")
@LoginValidator
public class UserController {

    @Autowired
    private RedisTemplate redisTemplate;

    /** 模拟的用户列表 */
    private static final List<User> PRE_USER_LIST = new ArrayList<User>() {
        private static final long serialVersionUID = 1L;
        {
            add(new User(1, "zhangsan", "123", true));
            add(new User(2, "lisi", "456", true));
            add(new User(3, "wangwu", "789", true));
        }
    };

    @PostMapping("/login")
    @LoginValidator(validated = false)
    public Result login(@RequestBody User user){
        String username = user.getUsername();
        String password = user.getPassword();
        if(StringUtils.isAnyBlank(username,password)){
            return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value()).errorMsg("用户名或者密码错误").build();
        }

        List<User> userList = PRE_USER_LIST.stream().filter(vo -> StringUtils.equals(username, vo.getUsername())).collect(Collectors.toList());
        if(userList.size() != 1){
            return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value()).errorMsg("用户名不存在").build();
        }
        User loginUser = userList.get(0);
        if(!StringUtils.equals(password, loginUser.getPassword())){
            return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value()).errorMsg("密码错误").build();
        }
        if(!loginUser.isEnable()){
            return Result.builder().code(HttpStatus.INTERNAL_SERVER_ERROR.value()).errorMsg("账户已经被锁定").build();
        }
        String token = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(Constant.REDIS_USER_PREFIX + token, loginUser, 30, TimeUnit.MINUTES);
        Object o = redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
        System.out.println(o.toString());
        return Result.builder().code(HttpStatus.OK.value()).data(token).build();
    }

    @PostMapping("/test")
    public String test(@RequestBody User user) {
        User user1 = LoginUserThread.get();
        System.out.println(user1.toString());
        return "测试编码";
    }
}```

## 1.使用aspect+注解+redis实现

```java
@Component
@Aspect
public class LoginAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 切点,方法上有注解或者类上有注解
     *  拦截标有注解的类或者方法
     */
    @Pointcut(value = "@annotation(com.zzc.hlh.annotition.LoginValidator) || @within(com.zzc.hlh.annotition.LoginValidator)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object before(ProceedingJoinPoint joinpoint) throws Throwable {
        // 获取方法方法上的LoginValidator注解
        MethodSignature methodSignature = (MethodSignature)joinpoint.getSignature();
        Method method = methodSignature.getMethod();
        LoginValidator loginValidator = method.getAnnotation(LoginValidator.class);
        // 如果有,并且值为false,则不校验
        if (loginValidator != null && !loginValidator.validated()) {
            return joinpoint.proceed(joinpoint.getArgs());
        }
        // 正常校验 获取request和response
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null || requestAttributes.getResponse() == null) {
            // 如果不是从前段过来的,没有request,则直接放行
            return joinpoint.proceed(joinpoint.getArgs());
        }
        HttpServletRequest request = requestAttributes.getRequest();
        HttpServletResponse response = requestAttributes.getResponse();
        // 获取token
        String token = request.getHeader(Constant.TOKEN_HEADER_NAME);
        if (StringUtils.isBlank(token)) {
            returnNoLogin(response);
            return null;
        }
        // 从redis中拿token对应user
        User user = (User) redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
        if (user == null) {
            returnNoLogin(response);
            return null;
        }
        // 存放如ThreadLocal
        LoginUserThread.put(user);
        // token续期
        Long templateExpire = redisTemplate.getExpire(Constant.REDIS_USER_PREFIX + token);
        if(templateExpire < 20*60){
            redisTemplate.expire(Constant.REDIS_USER_PREFIX + token, 30, TimeUnit.MINUTES);
        }
        //放行
        return joinpoint.proceed(joinpoint.getArgs());
    }

    /**
     * 返回未登录的错误信息
     * @param response ServletResponse
     */
    private void returnNoLogin(HttpServletResponse response) throws IOException {
        ServletOutputStream outputStream = response.getOutputStream();
        // 设置返回401 和响应编码
        response.setStatus(401);
        response.setContentType("Application/json;charset=utf-8");
        // 构造返回响应体
        Result<String> result = Result.<String>builder()
                .code(HttpStatus.UNAUTHORIZED.value())
                .errorMsg("未登陆,请先登陆")
                .build();
        String resultString = JSONUtil.toJsonStr(result);
        outputStream.write(resultString.getBytes(StandardCharsets.UTF_8));
    }
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginValidator {
    boolean validated() default true;
}

2.使用filter监听器

public class LoginFilter implements Filter {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LoginProperties loginProperties;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public LoginFilter(RedisTemplate redisTemplate, LoginProperties loginProperties) {
        this.redisTemplate = redisTemplate;
        this.loginProperties = loginProperties;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 过滤路径
        String requestURI = httpServletRequest.getRequestURI();
        if (!loginProperties.getFilterExcludeUrl().contains(requestURI)) {
            // 获取token
            String token = httpServletRequest.getHeader(Constant.TOKEN_HEADER_NAME);
            if (StringUtils.isBlank(token)) {
                returnNoLogin(response);
                return;
            }
            // 从redis中拿token对应user
            User user = (User) redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
            if (user == null) {
                returnNoLogin(response);
                return;
            }
            // 存放如ThreadLocal
            LoginUserThread.put(user);
            // token续期
            Long templateExpire = redisTemplate.getExpire(Constant.REDIS_USER_PREFIX + token);
            if(templateExpire < 20*60){
                redisTemplate.expire(Constant.REDIS_USER_PREFIX + token, 30, TimeUnit.MINUTES);
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }

    /**
     * 返回未登录的错误信息
     * @param response ServletResponse
     */
    private void returnNoLogin(ServletResponse response) throws IOException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        // 设置返回401 和响应编码
        httpServletResponse.setStatus(401);
        httpServletResponse.setContentType("Application/json;charset=utf-8");
        // 构造返回响应体
        Result<String> result = Result.<String>builder()
                .code(HttpStatus.UNAUTHORIZED.value())
                .errorMsg("未登陆,请先登陆")
                .build();
        String resultString = JSONUtil.toJsonStr(result);
        outputStream.write(resultString.getBytes(StandardCharsets.UTF_8));
    }
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private  LoginInterception loginInterception;
    @Autowired
    private LoginProperties loginProperties;
    @Autowired
    private RedisTemplate redisTemplate;
//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(loginInterception)
//                .addPathPatterns(loginProperties.getInterceptorIncludeUrl())
//                .excludePathPatterns(loginProperties.getInterceptorExcludeUrl());
//    }

    /*
     * 添加过滤器
     */
    @Bean
    public FilterRegistrationBean<Filter> loginFilterRegistration() {
        // 注册LoginFilter
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new LoginFilter(redisTemplate, loginProperties));
        // 设置名称
        registrationBean.setName("loginFilter");
        // 设置拦截路径
        registrationBean.addUrlPatterns(loginProperties.getFilterIncludeUrl().toArray(new String[0]));
        // 指定顺序
        registrationBean.setOrder(-1);
        return registrationBean;
    }
}

3.使用过滤器

@Component
public class LoginInterception implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 获取token
        String token = request.getHeader(Constant.TOKEN_HEADER_NAME);
        if (StringUtils.isBlank(token)) {
            returnNoLogin(response);
            return false;
        }
        User user = (User) redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
        if (user == null) {
            returnNoLogin(response);
            return false;
        }
        // 存放如ThreadLocal
        LoginUserThread.put(user);
        // token续期
        Long templateExpire = redisTemplate.getExpire(Constant.REDIS_USER_PREFIX + token);
        if(templateExpire < 20*60){
            redisTemplate.expire(Constant.REDIS_USER_PREFIX + token, 30, TimeUnit.MINUTES);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        LoginUserThread.remove();
    }

    /**
     * 返回未登录的错误信息
     * @param response ServletResponse
     */
    private void returnNoLogin(HttpServletResponse response) throws IOException {
        ServletOutputStream outputStream = response.getOutputStream();
        // 设置返回401 和响应编码
        response.setStatus(401);
        response.setContentType("Application/json;charset=utf-8");
        // 构造返回响应体
        Result<String> result = Result.<String>builder()
                .code(HttpStatus.UNAUTHORIZED.value())
                .errorMsg("未登陆,请先登陆")
                .build();
        String resultString = JSONUtil.toJsonStr(result);
        outputStream.write(resultString.getBytes(StandardCharsets.UTF_8));
    }
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private  LoginInterception loginInterception;
    @Autowired
    private LoginProperties loginProperties;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterception)
                .addPathPatterns(loginProperties.getInterceptorIncludeUrl())
                .excludePathPatterns(loginProperties.getInterceptorExcludeUrl());
    }
}

其它

public class LoginUserThread {

    /** 线程池变量 */
    private static final ThreadLocal<User> LOGIN_USER = new ThreadLocal<User>();

    private LoginUserThread() {}

    public static User get() {
        return LOGIN_USER.get();
    }

    public static void put(User user) {
        LOGIN_USER.set(user);
    }

    public static void remove() {
        LOGIN_USER.remove();
    }

}
public class Constant {

        /** redis存储的key的前缀 */
        public static final String REDIS_USER_PREFIX = "user:";
        /** token存储的请求头名称 */
        public static final String TOKEN_HEADER_NAME = "Authorization";

}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Result<T> implements Serializable {
    private static final long serialVersionUID = 9110032459932964235L;

    private int code;
    private String errorMsg;
    private T data;
}
@Component
@ConfigurationProperties(prefix = "login")
@Data
public class LoginProperties implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<String> filterIncludeUrl;
    private List<String> filterExcludeUrl;

    private List<String> interceptorIncludeUrl;
    private List<String> interceptorExcludeUrl;

}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private int id;
    private String username;
    private String password;
    private boolean enable;

}

```yaml
login:
  filter-include-url:
    - /*
  filter-exclude-url:
    - /user/login
  interceptor-include-url:
    - /**
  interceptor-exclude-url:
    - /user/login
    - /error/**```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值