要配合拦截器一起使用
先把需要的参数放到HttpServletRequest中的head中,然后在NativeWebRequest取出参数
先把参数放进HttpServletRequest中的head中request.setAttribute(REQUEST_CURRENT_USER, tokenUser);
package com.bsj.obd.authorization.interceptor;
import com.alibaba.fastjson.JSON;
import com.bsj.obd.authorization.annotation.Authorization;
import com.bsj.obd.authorization.annotation.Clear;
import com.bsj.obd.cached.RedisCached;
import com.bsj.obd.def.dto.TokenUser;
import com.bsj.obd.global.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
/**
* 自定义拦截器,对请求进行身份验证
*
* @date 2018/9/10 11:53
*/
@Component
@Slf4j
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
public static final String REQUEST_CURRENT_USER = "REQUEST_CURRENT_USER";
@Autowired
private RedisCached redisCached;
/**
* @desc 拦截请求,处理
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 判断请求的Controller类或方法是否有注解
boolean authorizationMethod = method.getAnnotation(Authorization.class) != null;
// String s=method.getName();
// log.info("当前调用的方法名"+s);
boolean clearMethod = method.getAnnotation(Clear.class) != null;
//判断类上有没有这个注解
boolean authorizationClazz = handlerMethod.getBeanType().getAnnotation(
Authorization.class) != null;
if (!(authorizationMethod || authorizationClazz) || clearMethod) {
// 为了防止以恶意操作直接在REQUEST_CURRENT_KEY写入key,将其设为null
request.setAttribute(REQUEST_CURRENT_USER, null);
return true;
}
String sessionId = request.getHeader("sessionId");
//验证token的值
if (StringUtils.isNotBlank(sessionId)) {
TokenUser tokenUser = redisCached.getUserInfo(sessionId);
if (tokenUser != null) {
request.setAttribute(REQUEST_CURRENT_USER, tokenUser);
// log.info("-------------->用户缓存信息:{}", UserCached.getAllUserId(tokenUser.getUserId()));
return true;
}
}
//返回授权错误码给前端
response.setStatus(401);
returnMessage(request, response, 1);
return false;
}
/**
* * @desc 返回token失效信息
*
* @param request
* @param response
* @throws IOException
*/
private void returnMessage(HttpServletRequest request, HttpServletResponse response, int type) throws IOException {
// 跨域配置
if (request.getHeader(HttpHeaders.ORIGIN) != null) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, HEAD");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "3600");
}
//这句话的意思,是让浏览器用utf8来解析返回的数据
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
if (type == 0) {
out.print(JSON.toJSONString(JsonResult.notAdminAuth()));
} else if (type == 1) {
out.print(JSON.toJSONString(JsonResult.notAuth()));
}
out.flush();
}
}
增加方法注入
在所有的TokenUser参数或CurrentUser注解的将自动注入参数
package com.bsj.obd.authorization.resolvers;
import com.bsj.obd.authorization.annotation.CurrentUser;
import com.bsj.obd.authorization.interceptor.AuthorizationInterceptor;
import com.bsj.obd.def.dto.TokenUser;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* 增加方法注入,将含有CurrentUser注解的方法参数注入当前登录用户
*/
public class CurrentUserMethodArgumentResolver<T> implements HandlerMethodArgumentResolver {
/**
* 判定是否有TokenUser参数或CurrentUser注解,返回true调用下面的方法resolveArgument。
*
* @param parameter
* @return
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(TokenUser.class)
|| parameter.hasParameterAnnotation(CurrentUser.class);
}
/**
* 真正用于处理参数分解的方法,将在AuthorizationInterceptor中的参数强转返回
*
* @param parameter
* @param mavContainer
* @param webRequest
* @param binderFactory
* @return
* @throws Exception
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
TokenUser userModel = (TokenUser) webRequest.getAttribute(AuthorizationInterceptor.REQUEST_CURRENT_USER,
RequestAttributes.SCOPE_REQUEST);
if (userModel != null) {
return userModel;
}
return null;
}
}