doum
2025-09-12 5e5a317f936e4e333809298930fb771fc0bdc9ac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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<String,Object> stringRedisTemplate;
    private long expireTime;
 
    public long getExpireTime() {
        return expireTime;
    }
 
    public void setExpireTime(long expireTime) {
        this.expireTime = 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(),"用户登陆已失效,请重新登陆!");
        }
        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<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];
        }
    }
}