zj
2026-01-05 a20da8817adb2342bd60f79e47487186a586f93a
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
package com.nq.common.interceptor;
 
 
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.nq.annotation.SameUrlData;
import com.nq.common.ServerResponse;
import com.nq.pojo.User;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.redis.JsonUtil;
import com.nq.utils.redis.RedisShardedPoolUtils;
import com.nq.utils.translate.GoogleTranslateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
@Component
public class ApiUserAuthorityInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(ApiUserAuthorityInterceptor.class);
 
 
    private RedisTemplate<String,String> redisTemplate;
 
    public ApiUserAuthorityInterceptor(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
 
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
//        httpServletResponse.setHeader("Access-Control-Allow-Origin",httpServletRequest.getHeader("origin"));
//        //该字段可选,是个布尔值,表示是否可以携带cookie
//        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
//        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT,PATCH, DELETE, OPTIONS");
//        httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
//        httpServletResponse.setHeader("Access-Control-Allow-Headers", "usertoken");
        if (HttpMethod.OPTIONS.toString().equals(httpServletRequest.getMethod())){
            return  true;
        }
 
        String url = httpServletRequest.getRequestURI();
        if ("/user/upload.do".equals(url)) {
            return true;
        }
        if ("/user/pay.do".equals(url)) {
            return true;
        }
        if ("/user/list.do".equals(url)) {
            return true;
        }
        if ("/user/newStockBuy.do".equals(url)) {
            return true;
        }
        if ("/user/buchahbds.do".equals(url)) {
            return true;
        }
        if ("/user/pay/flyPay.do".equals(url)) {
            return true;
        }
        if ("/user/rechargeCallback.do".equals(url)) {//支付回调
            return true;
        }
        if ("/user/rechargeCallbackTwo.do".equals(url)) {//支付回调
            return true;
        }
        if ("/user/rechargeCallbackZero.do".equals(url)) {//支付回调
            return true;
        }
        if ("/user/rechargeCallbackThree.do".equals(url)) {//支付回调
            return true;
        }
        if ("/user/payoutCallback.do".equals(url)) {//代付回调
            return true;
        }
        User currentUser = getCurrentUser(httpServletRequest);
        GoogleTranslateUtil googleTranslateUtil = new GoogleTranslateUtil();
        String lang = httpServletRequest.getHeader("lang");
        if (null == currentUser) {
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            PrintWriter writer = httpServletResponse.getWriter();
            writer.print( new Gson().toJson(ServerResponse.createByErrorCodeMsg(401,googleTranslateUtil.translate("请登录",lang ))));
            writer.flush();
            writer.close();
            return false;
        }
        String uri = httpServletRequest.getRequestURI();
        //验证重复点击与接口权限等
        Boolean checkFlag = checkUri(httpServletResponse, handler, uri,currentUser);
        if (!checkFlag) {
            return Boolean.FALSE;
        }
        //判断请求头
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
    }
 
    /**
     * token验证
     *
     * @param response 返回
     * @param handler  请求头
     * @return R 的统一返回,并拦截
     * @throws Exception 异常情况,则为服务异常
     */
    private Boolean checkUri(HttpServletResponse response, Object handler, String uri,User user) throws Exception {
        //判断连续请求的情况
        if (handler instanceof HandlerMethod) {
            SameUrlData tokenTypeAnnotation = findAnnotation((HandlerMethod) handler, SameUrlData.class);
            //判断是否需要验证连续点击
            if (tokenTypeAnnotation != null && redisTemplate.hasKey(user.getId() + uri)) {
                return responseWrite(response, "請勿頻繁點擊");
            } else {
                //将接口+用户信息存储到缓存中。进行重复点击校验
                redisTemplate.opsForValue().set(user.getId()+ uri, "", 30, TimeUnit.SECONDS);
            }
        }
        return true;
    }
 
    private Boolean responseWrite(HttpServletResponse response, String resultMSG) throws Exception {
        //throw new BaseException(resultCode);
//        定义返回类型为JSON
        response.setContentType("application/json;charset=UTF-8");
//        获取PrintWriter
        PrintWriter out = response.getWriter();
        //将异常类型写入
        ServerResponse<Object> byErrorMsg = ServerResponse.createByErrorMsg(resultMSG);
        out.write(JSON.toJSONString(byErrorMsg));
        //输出流
        out.flush();
        //关闭请求
        out.close();
        return true;
    }
 
    /**
     * 请求结束后进行的操作
     *
     * @param request  请求信息
     * @param response 返回信息
     * @param handler  请求头
     * @param ex       异常情况
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable
    Exception ex) {
        String uri = request.getRequestURI();
        if (handler instanceof HandlerMethod) {
            User currentUser = getCurrentUser(request);
            SameUrlData tokenTypeAnnotation = findAnnotation((HandlerMethod) handler, SameUrlData.class);
            //没有声明需要权限,或者声明不验证权限
            if (tokenTypeAnnotation != null) {
                redisTemplate.delete(currentUser.getId() + uri);
            }
        }
 
    }
 
    /**
     * 获取接口上的注解
     *
     * @param handler        请求方法
     * @param annotationType 想要获取的注解
     * @param <T>            想要获取的注解类型
     * @return 注解
     */
    private <T extends Annotation> T findAnnotation(HandlerMethod handler, Class<T> annotationType) {
        T annotation = handler.getBeanType().getAnnotation(annotationType);
        if (annotation != null) {
            return annotation;
        }
        return handler.getMethodAnnotation(annotationType);
    }
 
    /**
     * 当前用户token鉴权
     *
     * @param request 请求
     * @return 当前用户
     */
 
    public User getCurrentUser(HttpServletRequest request) {
        String property = PropertiesUtil.getProperty("user.cookie.name");
        String loginToken = request.getHeader(property);
        if (loginToken == null) {
            return null;
        }
        String userJson = RedisShardedPoolUtils.get(loginToken);
 
        if (userJson == null||"".equals(userJson)){
            return null;
        }
        return (User) JsonUtil.string2Obj(userJson, User.class);
    }
}