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 {
MethodSignature methodSignature = (MethodSignature)joinpoint.getSignature();
Method method = methodSignature.getMethod();
LoginValidator loginValidator = method.getAnnotation(LoginValidator.class);
if (loginValidator != null && !loginValidator.validated()) {
return joinpoint.proceed(joinpoint.getArgs());
}
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null || requestAttributes.getResponse() == null) {
return joinpoint.proceed(joinpoint.getArgs());
}
HttpServletRequest request = requestAttributes.getRequest();
HttpServletResponse response = requestAttributes.getResponse();
String token = request.getHeader(Constant.TOKEN_HEADER_NAME);
if (StringUtils.isBlank(token)) {
returnNoLogin(response);
return null;
}
User user = (User) redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
if (user == null) {
returnNoLogin(response);
return null;
}
LoginUserThread.put(user);
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());
}
private void returnNoLogin(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
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)) {
String token = httpServletRequest.getHeader(Constant.TOKEN_HEADER_NAME);
if (StringUtils.isBlank(token)) {
returnNoLogin(response);
return;
}
User user = (User) redisTemplate.opsForValue().get(Constant.REDIS_USER_PREFIX + token);
if (user == null) {
returnNoLogin(response);
return;
}
LoginUserThread.put(user);
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() {
}
private void returnNoLogin(ServletResponse response) throws IOException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
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;
@Bean
public FilterRegistrationBean<Filter> loginFilterRegistration() {
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 {
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;
}
LoginUserThread.put(user);
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();
}
private void returnNoLogin(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
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 {
public static final String REDIS_USER_PREFIX = "user:";
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:
-