package com.doumee.config.cloudfilter;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.doumee.config.annotation.CloudRequiredPermission;
|
import com.doumee.config.annotation.LoginNoRequired;
|
import com.doumee.config.jwt.JwtProperties;
|
import com.doumee.config.jwt.JwtTokenUtil;
|
import com.doumee.core.constants.ResponseStatus;
|
import com.doumee.core.exception.BusinessException;
|
import com.doumee.service.business.third.model.LoginUserInfo;
|
import com.doumee.core.utils.Constants;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
|
import javax.annotation.Resource;
|
import javax.servlet.ServletInputStream;
|
import javax.servlet.http.Cookie;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequestWrapper;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.BufferedReader;
|
import java.io.IOException;
|
import java.io.InputStreamReader;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
|
public class LoginHandlerInterceptor implements HandlerInterceptor {
|
|
private RedisTemplate<String,Object> stringRedisTemplate;
|
private long expireTime;
|
|
|
// 由于该类未交给spring管理,因此不能使用自动装配的方式获取RedisTemplate对象
|
public LoginHandlerInterceptor(RedisTemplate<String,Object> stringRedisTemplate,long expireTime) {
|
this.expireTime = expireTime;
|
this.stringRedisTemplate = stringRedisTemplate;
|
}
|
|
@Override
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
if(handler instanceof HandlerMethod){
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
Class<?> beanType = handlerMethod.getBeanType();
|
if (!beanType.isAnnotationPresent(LoginNoRequired.class) && !handlerMethod.hasMethodAnnotation(LoginNoRequired.class)) {
|
//获取token
|
Cookie[] cookies = request.getCookies();
|
String token = request.getHeader(Constants.HEADER_USER_TOKEN); // 从 http 请求头中取出 token
|
if(StringUtils.isBlank(token)){
|
for(Cookie c :cookies){
|
if(StringUtils.equals(c.getName(),Constants.HEADER_USER_TOKEN)){
|
token = c.getValue();
|
}
|
}
|
}
|
if (StringUtils.isNotBlank(token)) {
|
LoginUserInfo user = checkLogin(token);
|
if (handlerMethod.hasMethodAnnotation(CloudRequiredPermission.class)) {
|
CloudRequiredPermission p = handlerMethod.getMethodAnnotation(CloudRequiredPermission.class);
|
if(p.value()!=null && p.value().length>0){
|
boolean hasPermission = false;
|
for(String s :p.value()){
|
if(user.getPermissions()!=null){
|
for(String t :user.getPermissions()){
|
if(StringUtils.equals(t,s)){
|
hasPermission = true;
|
break;
|
}
|
}
|
}
|
}
|
if(!hasPermission) {
|
//没有操作权限
|
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"没有该操作权限");
|
}
|
}
|
|
}
|
/* try {
|
CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
|
String body = requestWrapper.getBody();
|
JSONObject object = JSONObject.parseObject(body);
|
if(object!=null){
|
object.put("loginUserinfo",user);
|
requestWrapper.setBody( JSONObject.toJSONString(object));
|
}
|
}catch (Exception e){
|
}*/
|
} else {
|
throw new BusinessException(ResponseStatus.NO_LOGIN.getCode(),request.getRequestURI()+"未登录,TOKEN缺失");
|
}
|
}
|
}else{
|
throw new BusinessException(ResponseStatus.NO_LOGIN.getCode(),request.getRequestURI()+"未登录");
|
}
|
|
return true;
|
}
|
|
private String getRequestBody(HttpServletRequest request) {
|
// 实现从request获取请求体的逻辑
|
String body = null;
|
ServletInputStream inputStream = null;
|
try {
|
inputStream = request.getInputStream();
|
String charset = request.getCharacterEncoding(); // 可能为null
|
if (charset == null) {
|
charset = "UTF-8"; // 默认编码
|
}
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset));
|
StringBuilder stringBuilder = new StringBuilder();
|
String line = null;
|
while ((line = reader.readLine()) != null) {
|
stringBuilder.append(line + "\n");
|
}
|
body = stringBuilder.toString();
|
} catch (IOException e) {
|
throw new RuntimeException(e);
|
}
|
|
return body;
|
}
|
|
private LoginUserInfo checkLogin(String token) {
|
if (token == null || token.isEmpty()) {
|
throw new BusinessException(ResponseStatus.NO_LOGIN.getCode(),"未登录");
|
}
|
String userinfo =(String) stringRedisTemplate.opsForValue().get(Constants.REDIS_TOKEN_KEY + token);
|
if (StringUtils.isBlank(userinfo)) {
|
throw new BusinessException(ResponseStatus.NO_LOGIN.getCode(),"未登录");
|
}
|
LoginUserInfo user = JSONObject.toJavaObject(JSONObject.parseObject(userinfo),LoginUserInfo.class );
|
if(user ==null ){
|
throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"用户登陆已失效,请重新登陆!");
|
}
|
stringRedisTemplate.expire(Constants.REDIS_TOKEN_KEY+token,this.expireTime, TimeUnit.MILLISECONDS);
|
//权限判断------------
|
return user;
|
}
|
|
|
|
// @Override
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
// UserContext.removeUser();
|
}
|
|
class RSARequestWrapper extends HttpServletRequestWrapper {
|
private Map<String, String[]> params = new HashMap<>();
|
/**
|
* 必须要实现的构造方法
|
* @param request
|
*/
|
public RSARequestWrapper(HttpServletRequest request) {
|
super(request);
|
//将参数表,赋予给当前的Map以便于持有request中的参数
|
this.params.putAll(request.getParameterMap());
|
}
|
/**
|
* 重载构造方法
|
* @param request
|
* @param extendParams
|
*/
|
public RSARequestWrapper(HttpServletRequest request, Map<String, Object> extendParams) {
|
this(request);
|
//这里将扩展参数写入参数表
|
addAllParameters(extendParams);
|
}
|
/**
|
* 在获取所有的参数名,必须重写此方法,否则对象中参数值映射不上
|
* @return
|
*/
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@Override
|
public Enumeration<String> getParameterNames() {
|
return new Vector(params.keySet()).elements();
|
}
|
/**
|
* 增加多个参数
|
* @param otherParams 增加的多个参数
|
*/
|
public void addAllParameters(Map<String, Object> otherParams) {
|
for (Map.Entry<String, Object> entry : otherParams.entrySet()) {
|
addParameter(entry.getKey(), entry.getValue());
|
}
|
}
|
/**
|
* 增加参数
|
* getParameterMap()中的类型是<String,String[]>类型的,所以这里要将其value转为String[]类型
|
* @param name 参数名
|
* @param value 参数值
|
*/
|
public void addParameter(String name, Object value) {
|
if (value != null) {
|
if (value instanceof String[]) {
|
params.put(name, (String[]) value);
|
} else if (value instanceof String) {
|
params.put(name, new String[]{(String) value});
|
} else {
|
params.put(name, new String[]{String.valueOf(value)});
|
}
|
}
|
}
|
@Override
|
public String[] getParameterValues(String name) {
|
String[] access_token_user_id = params.get("access_token_user_id");
|
String[] values = params.get(name);//getValue(name);
|
if (values == null || access_token_user_id==null){
|
return null;
|
}
|
return values;
|
}
|
|
@Override
|
public String getParameter(String name) {
|
String[] access_token_user_id = params.get("access_token_user_id");
|
String[] values = params.get(name);//getValue(name);
|
if (values == null || access_token_user_id==null){
|
return null;
|
}
|
return values[0];
|
}
|
}
|
}
|