Spring Boot + redis 配置拦截器实现权限验证
2020-03-17 本文已影响0人
zhangweisep
拦截器配置
package com.yuhan.mkt.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.yuhan.mkt.annotation.AuthToken;
import com.yuhan.mkt.util.EmptyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
/**
* Filename: ttee
* Author: Zhang Wei
* Date: 2018/8/29 16:12
* Description:
* History:
*/
@Slf4j
public class AuthorizationInterceptor implements HandlerInterceptor {
//存放鉴权信息的Header名称,默认是Authorization
private String httpHeaderName = "Authorization";
//鉴权失败后返回的错误信息,默认为401 unauthorized
private String unauthorizedErrorMessage = "401 unauthorized";
//鉴权失败后返回的HTTP错误码,默认为401
private int unauthorizedErrorCode = HttpServletResponse.SC_UNAUTHORIZED;
private static ApplicationContext applicationContext;
private StringRedisTemplate stringRedisTemplate;
public static void setStringRedisTemplate(ApplicationContext applicationContext){
AuthorizationInterceptor.applicationContext = applicationContext;
}
/**
* 存放登录用户模型Key的Request Key
*/
public static final String REQUEST_CURRENT_KEY = "REQUEST_CURRENT_KEY";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
stringRedisTemplate = applicationContext.getBean(StringRedisTemplate.class);
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 如果打上了AuthToken注解则需要验证token
if (method.getAnnotation(AuthToken.class) != null || handlerMethod.getBeanType().getAnnotation(AuthToken.class) != null) {
String token = request.getHeader(httpHeaderName);
log.info("token is {}", token);
String username = "";
if (token != null && token.length() != 0) {
username = stringRedisTemplate.opsForValue().get(token);
Long tokeBirthTime = stringRedisTemplate.getExpire(token, TimeUnit.SECONDS);
log.info("redis缓存用户名 is {}", username);
log.info("过期时间 {}", tokeBirthTime);
if(tokeBirthTime > 0 && EmptyUtil.isNotEmpty(username)){
stringRedisTemplate.opsForValue().set(token, username, 60*60, TimeUnit.SECONDS);
request.setAttribute(REQUEST_CURRENT_KEY, username);
return true;
}
}
JSONObject jsonObject = new JSONObject();
PrintWriter out = null;
try {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setStatus(unauthorizedErrorCode);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
jsonObject.put("code", ((HttpServletResponse) response).getStatus());
jsonObject.put("message", HttpStatus.UNAUTHORIZED);
out = response.getWriter();
out.println(jsonObject);
return false;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != out) {
out.flush();
out.close();
}
}
}
request.setAttribute(REQUEST_CURRENT_KEY, null);
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 {
}
}
权限拦截自定义注解
package com.yuhan.mkt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Filename: ttee
* Author: Zhang Wei
* Date: 2018/8/29 16:12
* Description: 自定义注解(Token验证)
* 使用该注解的类、方法等都需要经过Token验证
* History:
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
}
使用方法
/**
* 退出登录
* 加入AuthToken注解的方法都会进入拦截器进行权限验证
* @param userJson
* @return
* @throws Exception
*/
@AuthToken
@ApiOperation(value = "退出登录", notes = "param:UserJson")
@RequestMapping(value = "/logout", method = RequestMethod.POST)
public Object logout(@RequestBody UserJson userJson) throws Exception{
if(EmptyUtil.isEmpty(userJson) || EmptyUtil.isEmpty(userJson.getToken())){
return ResultUtil.error(ExceptionEnum.PARAM_NULL);
}
Result result = userService.logout(userJson);
return result;
}
pom.xml依赖包
<!--redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>