1
13693261870
2022-09-16 fee60c3e25fac0982f3b8cb8feea7225c4ed22f8
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
package com.terra.proxy.controller;
 
import java.util.*;
 
import javax.servlet.http.HttpServletRequest;
 
import cn.hutool.core.collection.CollectionUtil;
import com.terra.proxy.util.JedisUtils;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.terra.proxy.bean.CustomerToken;
import com.terra.proxy.bean.ResActionRecord;
import com.terra.proxy.bean.TokenRecord;
import com.terra.proxy.mapper.LogMapper;
import com.terra.proxy.service.Impl.LogServiceImpl;
import com.terra.proxy.service.Impl.ResActionRecordServiceImpl;
import com.terra.proxy.service.Impl.ServerRegisterServiceImpl;
import com.terra.proxy.util.HttpContextUtils;
import com.terra.proxy.util.JwtUtils;
import com.terra.proxy.util.Result;
 
import cn.hutool.json.JSONUtil;
import io.jsonwebtoken.Claims;
import redis.clients.jedis.Jedis;
 
/**
 * token生成与验证
 * 
 * @author TanBin
 * @date 2018年1月31日 下午6:26:13
 */
@RestController
public class TokenController  {
 
    @Autowired
    public Environment env;
    
    @Autowired
    LogServiceImpl logservice;
    
    @Autowired
    ResActionRecordServiceImpl actionRecordService;
    
    @Autowired
    private JwtUtils jwtUtils;
    
    @Autowired
    JedisUtils jedisUtils;
 
    @Value("${sys.allowedips}")
    private String allowedips;
    @Value("${sys.jwt.expire}")
    private Long expireSeconds;
 
    @Autowired
    ServerRegisterServiceImpl serverRegisterService;
    
    @Autowired
    LogMapper logMapper;
    
    private static final Logger log = LoggerFactory.getLogger(TokenController.class);
    
    
    @RequestMapping(value = "/token/getToken", method = { RequestMethod.POST, RequestMethod.GET })
    public  String getToken(String message,long expireSeconds)
    {
        // 生成token
        String token = jwtUtils.generateToken( message.toString(), expireSeconds);
        return token;
    }
    
    @RequestMapping(value="/token/delTokenRecord",method = {RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public String delToken(String token,Integer expiration){
        Jedis jedis=JedisUtils.getJedis();
        String t="zytoken:"+token;
        try{
        Map<String, Object> params =new HashMap<>();
        params.put("token", token);
        params.put("expiration", -1);
        jedis.del(t);
        //除去自动续约token
        jedis.srem("autoToken",token);
        logservice.updateTokenRecord(params);
        }catch (Exception e) {
         e.printStackTrace();
        }
         return "success";
    }
 
 
 
    
    
    @RequestMapping(value="/token/selectTokenRecord",method = {RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public String selectTokenRecord(Integer limit,Integer page,String token,Integer tokenstatus,String identyinfo,Integer resourceId){
        Map<String, Object> params =new HashMap<>();
        params.put("limit", limit);
        params.put("page",  (page-1)*limit);
        params.put("token", token);
        params.put("tokenstatus", tokenstatus);
        params.put("identyinfo", identyinfo);
        params.put("resourceId", resourceId);
        List<Map> list=logservice.selectTokenRecord(params);
        Jedis jedis = JedisUtils.getJedis();
        //自动续约列表
        Set<String> autoToken = jedis.smembers("autoToken");
        list.stream().forEach(map -> {
            String string = map.get("TOKEN").toString();
            if(StringUtils.isNotEmpty(string)&&autoToken.contains(string)){
                map.put("AUTOTOKEN","1");
            }else {
                map.put("AUTOTOKEN","0");
            }
        });
        JedisUtils.close(jedis);
        JSONObject json=new JSONObject();
        json.put("total", logservice.getTotalTokenRecord(params));
        json.put("data", list);
        json.put("totalpage",Math.ceil((double) logservice.getTotalTokenRecord(params)/(double)limit));
        return JSONObject.toJSONStringWithDateFormat(json, "yyyy-MM-dd HH:mm:ss", SerializerFeature.PrettyFormat);
    }
 
    @RequestMapping(value = "/token/tokenTimeExtend", method = { RequestMethod.POST, RequestMethod.GET })
    public  String tokenTimeExtend(String  tokenlist,Integer expireSeconds)
    {   Jedis jedis= JedisUtils.getJedis();
        Map<String, Object> params =new HashMap<>();
    if (StringUtils.isEmpty(tokenlist)) return Result.ok().toString();
    if(null==expireSeconds) expireSeconds= this.expireSeconds.intValue();
        try{
            String[] tokens=tokenlist.split(";");
            for(String t : tokens){
                String token="zyToken:"+t;
                String s = jedis.get(token);
                if(StringUtils.isEmpty(s)){
                    //如果已经过期 重新加入redis 并且更新数据
                    jedis.setex(token,expireSeconds,"1");
                }else {
                    //如果没过期 过期时间加长
                    Long ttl = jedis.ttl(token);
                    int time=Integer.parseInt(String.valueOf(ttl+expireSeconds));
                    expireSeconds=time;
                    jedis.setex(token,time,"1");
                }
 
                params.put("token", t);
                params.put("expiration", expireSeconds);
                params.put("applytime", new Date());
                logservice.updateTokenRecord(params);    
            }
        }catch (Exception e){
            e.printStackTrace();
 
        }finally {
            jedis.close();
        }
 
        return "ok";
    }
 
    @RequestMapping(value = "/token/decToken", method = { RequestMethod.POST, RequestMethod.GET })
    public  String decToken(String token)
    {
        Claims claims = jwtUtils.getClaimByToken(token);
        if (claims == null || jwtUtils.isTokenExpired(claims.getExpiration())) {
            return   "token已失效";
        }
        return claims.getSubject();
    }
 
 
    /**
     * 生成用户访问资源服务token
     * 调用示例:token/generate?loginName=landtoollxb&resourceId=&resourceUrl=&expireSeconds=&clientIp=
     *
     * @param userid
     * @param resourceId
     * @param expireSeconds
     * @param clientIp
     * @param subzyids
     * @param isPubzy
     * @return
     */
    private Result generateByloginName(Integer userid, String resourceId,   Long expireSeconds,
            String clientIp,String subzyids,Boolean isPubzy) {
        if ( userid==0) {
            return Result.error("缺少userid参数");
        }
        if (StringUtils.isBlank(resourceId)) {
            return Result.error("缺少resourceId参数");
        }
         
        if (StringUtils.isBlank(clientIp)) {
            return Result.error("缺少clientIp参数");
        }
        CustomerToken cutToken=new CustomerToken(); 
        cutToken.setResourceId(resourceId);
        cutToken.setClientIp(clientIp);
        cutToken.setUserid(userid.toString()); 
        cutToken.setSubzyids(subzyids);
        cutToken.setIsPubzy(isPubzy); 
        
        // 生成token
        String token = jwtUtils.generateToken( cutToken.toString(), expireSeconds);
        SaveTokenRecord( expireSeconds, "用户"+userid+"生成", token, cutToken, clientIp);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getClaimByToken(token).getExpiration());
        Result r = Result.ok().put(map);
        return r;
    }
 
 
    /**
     * 系统内部使用
     * 生成token
     * 调用示例:token/generate?loginName=landtoollxb&resourceId=&resourceUrl=&expireSeconds=&clientIp=
     *
     * @param userid
     * @param resourceId
     * @param expireSeconds
     * @param clientIp
     * @param subzyids
     * @param isPubzy
     * @return
     */
    @RequestMapping(value = "/token/generate", method = { RequestMethod.POST, RequestMethod.GET })
    public Result generate(Integer userid, String resourceId,   Long expireSeconds,String clientIp,String subzyids,Boolean isPubzy) {
        Map<String, Object> msg = new HashMap<>();
        //判读IP是否合法------
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        String ip = request.getLocalAddr();
        
        //判读IP是否合法------
        if(!checkIp(ip))
        {
            return Result.error("非法IP调用【"+ip+"】");
        }
         
        Result r = generateByloginName(userid, resourceId, expireSeconds, clientIp, subzyids,isPubzy);
 
        return r;
    }
 
 
 
    
    
    /**
     * 系统内部使用
     * 生成token
     * 调用示例:token/appgenerate?resourceId=&resourceUrl=&expireSeconds=&appId=&appUrl=
     * 
     * @param resourceId
     * @param resourceId
     * @param expireSeconds
     * @param appId
     * @param appUrl
     * @return
     */
 
    @RequestMapping(value = "/token/appgenerate", method = { RequestMethod.POST, RequestMethod.GET })
    public Result appGenerate(Integer userId,String resourceId, Long expireSeconds, Long appId, String appUrl,String subzyids) {
 
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        String clientIp = request.getLocalAddr();
        
        //判读IP是否合法------
        if(!checkIp(clientIp))
        {
            return Result.error("非法IP调用【"+clientIp+"】");
        }
        if (StringUtils.isBlank(resourceId)) {
            return Result.error("缺少resourceId参数");
        } 
        if (null == appId) {
            return Result.error("缺少appId参数");
        }
        if (StringUtils.isBlank(appUrl)) {
            return Result.error("缺少appUrl参数");
        }
        
        CustomerToken cutToken=new CustomerToken(); 
        cutToken.setResourceId(resourceId);
        cutToken.setAppId(appId.toString());
        cutToken.setAppUrl(appUrl);
        cutToken.setUserid( userId.toString());
        cutToken.setSubzyids(subzyids);
        
        // 生成token
        String token = jwtUtils.generateToken(cutToken.toString(), expireSeconds);
        SaveTokenRecord( expireSeconds, "应用系统"+appId+"生成", token, cutToken, clientIp);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getClaimByToken(token).getExpiration());
        Result r = Result.ok().put(map);
 
        return r;
    }
     
    
    /**
     * "?resourceId=" + resourceId
     + "&requestUrl=" + requestUrl + "&clientIp=" + clientIp
     + "&refererUrl=" + referer + "&token=" + token;
     * 验证token 调用示例:token/validate?token=&requestUrl=&clientip=
     * 或:token/validate?token=&requestUrl=&refererUrl=
     * 目前日志记录有问题:loginName在Token里面,记录不到。
     * @param token
     * @param requestUrl
     * @param clientIp
     * @param refererUrl
     * @return
     */
 
    @RequestMapping(value = "/token/validate", method = { RequestMethod.POST, RequestMethod.GET })
    public Result validate(String token, String requestUrl, String clientIp, String refererUrl,String resourceId) {
        // 校验token
        if (StringUtils.isBlank(token)) {
            return Result.error(HttpStatus.SC_UNAUTHORIZED, "未传入token");
        }
        Claims claims = jwtUtils.getClaimByToken(token);
        if (claims == null || jwtUtils.isTokenExpired(claims.getExpiration())) {
            return Result.error(HttpStatus.SC_UNAUTHORIZED, "token已失效");
        }
 
        String msg = claims.getSubject();
        CustomerToken cutToken=CustomerToken.fromString(msg);
 
        String appId =cutToken.getAppId();
        // 无appId属通过浏览器直接访问的情况:校验 clientIp 与 Token里面的IP地址是否匹配,
        if (StringUtils.isBlank(appId)) {
            //资源池系统采用APPToken 方式校验,解决专题地图里面图层其他用户访问IP校验不通过问题
            //如果本地ArcMap调用资源池里面的图层后发布服务,仍然会存在其他用户访问IP校验不通过问题----lxb(延后解决)
             
             log.info("传入IP:"+clientIp +"加密时申请IP:"+(String) cutToken.getClientIp() );
            if (StringUtils.isBlank(clientIp) || !clientIp.equalsIgnoreCase((String) cutToken.getClientIp())) {
                return Result.error(HttpStatus.SC_UNAUTHORIZED, "未授权的客户端");
            }
 
            // 有appId属通过app访问的情况:校验 refererUrl 与 Token里面的appUrl地址是否匹配
        } else {
             log.info("传入refererUrl:"+refererUrl +"加密时申请appUrl:"+(String) cutToken.getAppUrl() );
            
            if (StringUtils.isBlank(refererUrl) || !refererUrl.startsWith((String) cutToken.getAppUrl())) {
                return Result.error(HttpStatus.SC_UNAUTHORIZED, "未授权的应用系统");
            }
        }
        
        //记录日志
        saveLogAction(cutToken,resourceId);
        //如果是专题底图,并且包含有不公开的图层资源,则返回资源ID列表. 
        Result r = Result.ok(cutToken.getSubzyids() );
        return r;
    }
 
    private void saveLogAction(CustomerToken map,String resourceId){
        ResActionRecord record = new ResActionRecord();
        //解密 Token 里包含userid的取那值,没有取0
        Long userid =Long.parseLong( map.getUserid()) ;//")!=null?Long.parseLong(map.get("userId").toString()):0L;
        record.setUserid(userid);
        Integer appid =Integer.parseInt(  map.getAppId());//map.get("appId")!=null?Integer.parseInt(map.get("appId").toString()):0;
        record.setAppid(appid);
        record.setResourceid(resourceId.length()!=0? Integer.parseInt(resourceId):0);
        actionRecordService.save(record);
    }
    
    private Boolean  checkIp(String ip)
    {
        Boolean rsult=false ;
        String whiteIPlist = env.getProperty("whiteIPlist");
        if(StringUtils.contains(whiteIPlist, ip))
        {
            rsult=true;
        }
        return rsult;
    }
    
    
    
    /**
     * 外部调用
     * 临时token获取
     * @param resourceid 资源id
     * @param req
     * @param expiration 失效时间
     * @param identyinfo  备注信息 表明 token使用人
     * @param appUrl     申请token系统地址
     * @param isPubzy    公开级别
     * @param appId      应用id
     * @param applyuserid  token申请人用户id
     * @return
     */
    @RequestMapping(value = "/genToken", method = RequestMethod.GET)
    public @ResponseBody String genToken(String resourceid,HttpServletRequest req,Long expiration,String identyinfo,String appUrl,Boolean isPubzy,String appId,String applyuserid ) {
        String clientIp = req.getLocalAddr();
        JSONObject json=new JSONObject();
        Jedis jedis = jedisUtils.getJedis();
        try {
            CustomerToken cutToken=new CustomerToken(); 
            cutToken.setResourceId(resourceid);
            cutToken.setUserid(applyuserid);
            cutToken.setAppUrl(appUrl);
            cutToken.setIsPubzy(isPubzy);
            cutToken.setAppId(appId);
            cutToken.setClientIp(req.getRemoteHost());
            cutToken.setRemark(identyinfo);
            String token = expiration!=null?jwtUtils.generateToken(cutToken.toString(), expiration):jwtUtils.generateToken(cutToken.toString(), expireSeconds);
            SaveTokenRecord( expiration, identyinfo, token, cutToken, clientIp);
            jedis.setex("zytoken:"+token,expiration!=null?expiration.intValue():expireSeconds.intValue(), "1");
            json.put("code", 200);
            json.put("data", token);
            json.put("message", "获取成功");
            return json.toJSONString();
        } catch (Exception e) {
            e.printStackTrace();
 
        } finally {
            jedis.close();
        }
        return "error";
    }
    /**
     * 取消自动续约的Token
     * @param token   token值
     */
    @RequestMapping("/token/delAutoToken")
    public void delAutoToken(@RequestParam String token){
        if(StringUtils.isNotEmpty(token)){
            Jedis jedis = JedisUtils.getJedis();
            jedis.srem("autoToken",token);
            JedisUtils.close(jedis);
        }
    }
    
    /**
     * 记录生成的Token
     * @param expiration 持续时间
     * @param identyinfo  备注信息,为jwt中间的数据部分
     * @param token   token值
     * @param cutToken  token对象类
     * @param
     */
    public void SaveTokenRecord(Long expiration,String identyinfo,String token,CustomerToken cutToken,String clientIp){
        TokenRecord record=new TokenRecord();
        record.setApplytime(new Date());
        record.setExpiration(expiration!=null?expiration.intValue():expireSeconds.intValue());
        record.setResourceid(Integer.valueOf(cutToken.getResourceId()));
        record.setIdentyinfo(identyinfo);
        record.setTokeninfo(cutToken.toString());
        record.setToken(token);
        record.setTokenapplyer(clientIp);
        logMapper.saveTokenRecord(record);
    }
 
 
    /**
     * 外部调用
     * 临时token获取
     * @param resourceid 资源id
     * @param req
     * @param expiration 失效时间
     * @param identyinfo  备注信息 表明 token使用人
     * @param appUrl     申请token系统地址
     * @param isPubzy    公开级别
     * @param appId      应用id
     * @param applyuserid  token申请人用户id
     * @return
     */
    @RequestMapping(value = "/genTokenForApply", method = RequestMethod.GET)
    public @ResponseBody String genTokenForApply(String resourceid,HttpServletRequest req,Long expiration,String identyinfo,String appUrl,Boolean isPubzy,String appId,String applyuserid,String isNever ) {
        // 已经存在的token 直接返回token
        Map<String, Object> param = new HashMap<>();
        param.put("resourceid", Integer.parseInt(resourceid));
        param.put("userid", applyuserid);
        List<Map> maps = serverRegisterService.queryServer(param);
        if (CollectionUtil.isNotEmpty(maps)) {
            String tokenTemp = logservice.queryToken(param);
            JSONObject json = new JSONObject();
            boolean tokenIsExtend = ZiyuanRightManager.CheckTokenIsExtend(tokenTemp);
            if (tokenIsExtend) {
                json.put("code", 200);
                json.put("data", tokenTemp);
                return json.toJSONString();
            }
            String clientIp = req.getLocalAddr();
            Jedis jedis = jedisUtils.getJedis();
            try {
                CustomerToken cutToken = new CustomerToken();
                cutToken.setResourceId(resourceid);
                cutToken.setUserid(applyuserid);
                cutToken.setAppUrl(appUrl);
                cutToken.setIsPubzy(isPubzy);
                cutToken.setAppId(appId);
                cutToken.setClientIp(req.getRemoteHost());
                cutToken.setRemark(identyinfo);
                if (expiration == null) {
                    expiration = expireSeconds * 30;
                }
                String token = expiration != null ? jwtUtils.generateToken(cutToken.toString(), expiration) : jwtUtils.generateToken(cutToken.toString(), expireSeconds); //默认给30天
                SaveTokenRecord(expiration, identyinfo, token, cutToken, clientIp);
                if (StringUtils.equals(isNever, "1")) {
                    jedis.set("zytoken:" + token, "1"); //永久有效
                } else {
                    jedis.setex("zytoken:" + token, expiration != null ? expiration.intValue() : expireSeconds.intValue(), "1");
                }
                jedis.setex("zytoken:" + token, expiration != null ? expiration.intValue() : expireSeconds.intValue(), "1");
                json.put("code", 200);
                json.put("data", token);
                json.put("message", "获取成功");
                return json.toJSONString();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jedis.close();
            }
            return "error";
        }
        return "error";
    }
}