需求:用户未登录时,只显示登录界面,登录后才能看到菜单及界面。
在后面每个controller接收客户端请求的方法上,都加上需要认证的注解。未登录的话,返回未登录返回码,客户端收到未登录返回码,则跳到登录界面
1.编写一个注解
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysToken {
String value() default "true";
}
2.编写一个拦截器
@Component
public class AuthTokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (this.checkNrefreshAuthTocken(request, response, handler)) {
return true;
}
return false;
}
private boolean checkNrefreshAuthTocken(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
if (!(handler instanceof HandlerMethod))
return true;
Map cookieAttr = null;
PromiseUser promiseUser = null;
Long loyalIdSetTime = null;
try {
cookieAttr = UserUtil.getLoginInfoFromRequest(request);
} catch (InvalidSignatureException | UserNotLoginException e) {
promiseUser = null;
} catch (Exception e) {
e.printStackTrace();
response.sendError(500);
return false;
}
if (!CollectionUtils.isEmpty(cookieAttr)) {
promiseUser = (PromiseUser) cookieAttr.get("promiseUser");
request.setAttribute("loyalPromiseUser", promiseUser);
loyalIdSetTime = (Long) cookieAttr.get("loyalIdSetTime");
request.setAttribute("loyalIdSetTime", (Long) cookieAttr.get("loyalIdSetTime"));
}
try {
//刷新cookie,要在preHandle中做,不能在postHandle中做,因为postHandle中,response已经commit了
refreshAuthTocken(response, promiseUser, loyalIdSetTime);
AuthToken authToken = getAuthTokenAnnotation(handler);
//如无注解,返回正常执行
if (authToken == null)
return true;
//有注解,cookie信息无效
if (CollectionUtils.isEmpty(cookieAttr) || promiseUser == null) {
buildErrorResponseInfo(response);
return false;
}
} catch (Exception e) {
e.printStackTrace();
response.sendError(500);
return false;
}
return true;
}
private void refreshAuthTocken(HttpServletResponse response, PromiseUser promiseUser, Long loyalIdSetTime) throws UnsupportedEncodingException, NoSystemPropertyException {
if (promiseUser != null) {
if (loyalIdSetTime == null)
loyalIdSetTime = 0L;
if ((System.currentTimeMillis() - loyalIdSetTime) >= Long.parseLong(SystemProperties.getProperty(SystemProperties.REFRESH_LOYAL_ID_TIME))) {
UserUtil.buildLoginCookie(response, promiseUser);
}
}
}
private AuthToken getAuthTokenAnnotation(Object handler) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取方法上的注解
AuthToken authToken = handlerMethod.getMethod().getAnnotation(AuthToken.class);
// 如果方法上的注解为空 则获取类的注解
if (authToken == null) {
authToken = handlerMethod.getMethod().getDeclaringClass().getAnnotation(AuthToken.class);
}
return authToken;
}
private void buildErrorResponseInfo(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
// Map<String, String> resMap = new HashMap<String, String>();
// resMap.put("result","fail");
// resMap.put("returnCode","C100002");
// resMap.put("message", ReturnCode.getMessage("C100002"));
ServiceResponse result = new ServiceResponse();
result.setStatus(ReturnCode.NOT_LOGIN);
result.setMessage(ReturnCode.getMessage(ReturnCode.NOT_LOGIN));
out = response.getWriter();
out.append(JsonUtil.toJson(result));
}
}
第三步:编写过滤器
@Configuration
public class SystemBluMvcConfig implements WebMvcConfigurer {
@Bean
public SysTokenInterceptor securityInterceptor() {
return new SysTokenInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(securityInterceptor()).excludePathPatterns("/admin/login")
.addPathPatterns("/**");
}
@Bean
public CommonsMultipartResolver getCommonMultipartResolver() {
return new CommonsMultipartResolver();
}
}
第四步:在Controller类的方法中加注解
@SysToken
@RequestMapping(path = "/menu", method = RequestMethod.GET)
public ServiceResponse getAllMenuTree() {
}
这样就可以了