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 lombok.extern.slf4j.Slf4j; 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; @Slf4j public class LoginHandlerInterceptor implements HandlerInterceptor { private RedisTemplate stringRedisTemplate; private long expireTime; public long getExpireTime() { return expireTime; } public void setExpireTime(long expireTime) { this.expireTime = expireTime; } // 由于该类未交给spring管理,因此不能使用自动装配的方式获取RedisTemplate对象 public LoginHandlerInterceptor(RedisTemplate 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(),"用户登陆已失效,请重新登陆!"); } log.error("=========开始刷新token有效期:"+token+"======time:"+this.getExpireTime()); stringRedisTemplate.expire(Constants.REDIS_TOKEN_KEY+token,this.getExpireTime(), 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 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 extendParams) { this(request); //这里将扩展参数写入参数表 addAllParameters(extendParams); } /** * 在获取所有的参数名,必须重写此方法,否则对象中参数值映射不上 * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Enumeration getParameterNames() { return new Vector(params.keySet()).elements(); } /** * 增加多个参数 * @param otherParams 增加的多个参数 */ public void addAllParameters(Map otherParams) { for (Map.Entry entry : otherParams.entrySet()) { addParameter(entry.getKey(), entry.getValue()); } } /** * 增加参数 * getParameterMap()中的类型是类型的,所以这里要将其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]; } } }