首页 > 代码库 > Java 两种方式实现Token校验

Java 两种方式实现Token校验

方法一:AOP

代码如下定义一个权限注解

 

[java] view plain copy
 
  1. package com.thinkgem.jeesite.common.annotation;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. /** 
  9.  * 权限注解 
  10.  * Created by Hamming on 2016/12/26. 
  11.  */  
  12. @Target(ElementType.METHOD)//这个注解是应用在方法上  
  13. @Retention(RetentionPolicy.RUNTIME)  
  14. public @interface AccessToken {  
  15. /*    String userId(); 
  16.     String token();*/  
  17. }  

获取页面请求中的ID token

[java] view plain copy
 
  1. @Aspect  
  2. @Component  
  3. public class AccessTokenAspect {  
  4.   
  5.     @Autowired  
  6.     private ApiService apiService;  
  7.   
  8.     @Around("@annotation(com.thinkgem.jeesite.common.annotation.AccessToken)")  
  9.     public Object doAccessCheck(ProceedingJoinPoint pjp) throws Throwable{  
  10.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
  11.         String id = request.getParameter("id");  
  12.         String token = request.getParameter("token");  
  13.         boolean verify = apiService.verifyToken(id,token);  
  14.         if(verify){  
  15.             Object object = pjp.proceed(); //执行连接点方法  
  16.             //获取执行方法的参数  
  17.   
  18.             return object;  
  19.         }else {  
  20.             return ResultApp.error(3,"token失效");  
  21.         }  
  22.     }  
  23. }  

 

token验证类  存储用到redis

 

[java] view plain copy
 
  1. package com.thinkgem.jeesite.common.service;  
  2.   
  3. import com.thinkgem.jeesite.common.utils.JedisUtils;  
  4. import io.jsonwebtoken.Jwts;  
  5. import io.jsonwebtoken.SignatureAlgorithm;  
  6. import io.jsonwebtoken.impl.crypto.MacProvider;  
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.stereotype.Service;  
  11. import org.springframework.transaction.annotation.Transactional;  
  12. import redis.clients.jedis.Jedis;  
  13.   
  14. import java.io.*;  
  15. import java.security.Key;  
  16. import java.util.Date;  
  17.   
  18. /** 
  19.  *token登陆验证 
  20.  * Created by Hamming on 2016/12/23. 
  21.  */  
  22. @Service  
  23. public class ApiService {  
  24.     private static final String at="accessToken";  
  25.   
  26.     public static Key key;  
  27.   
  28. //    private Logger logger = LoggerFactory.getLogger(getClass());  
  29.     /** 
  30.      * 生成token 
  31.      * Key以字节流形式存入redis 
  32.      * 
  33.      * @param date  失效时间 
  34.      * @param appId AppId 
  35.      * @return 
  36.      */  
  37.     public String generateToken(Date date, String appId){  
  38.         Jedis jedis = null;  
  39.         try {  
  40.             jedis = JedisUtils.getResource();  
  41.             byte[] buf = jedis.get("api:key".getBytes());  
  42.             if (buf == null) { // 建新的key  
  43.                 key = MacProvider.generateKey();  
  44.                 ByteArrayOutputStream bao = new ByteArrayOutputStream();  
  45.                 ObjectOutputStream oos = new ObjectOutputStream(bao);  
  46.                 oos.writeObject(key);  
  47.                 buf = bao.toByteArray();  
  48.                 jedis.set("api:key".getBytes(), buf);  
  49.             } else { // 重用老key  
  50.                 key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();  
  51.             }  
  52.   
  53.         }catch (IOException io){  
  54. //            System.out.println(io);  
  55.         }catch (ClassNotFoundException c){  
  56. //            System.out.println(c);  
  57.         }catch (Exception e) {  
  58. //            logger.error("ApiService", "generateToken", key, e);  
  59.         } finally {  
  60.             JedisUtils.returnResource(jedis);  
  61.         }  
  62.   
  63.         String token = Jwts.builder()  
  64.                 .setSubject(appId)  
  65.                 .signWith(SignatureAlgorithm.HS512, key)  
  66.                 .setExpiration(date)  
  67.                 .compact();  
  68.         // 计算失效秒,7889400秒三个月  
  69.         Date temp = new Date();  
  70.         long interval = (date.getTime() - temp.getTime())/1000;  
  71.         JedisUtils.set(at+appId ,token,(int)interval);  
  72.         return token;  
  73.     }  
  74.   
  75.     /** 
  76.      * 验证token 
  77.      * @param appId AppId 
  78.      * @param token token 
  79.      * @return 
  80.      */  
  81.     public boolean verifyToken(String appId, String token) {  
  82.         if( appId == null|| token == null){  
  83.             return false;  
  84.         }  
  85.         Jedis jedis = null;  
  86.         try {  
  87.             jedis = JedisUtils.getResource();  
  88.             if (key == null) {  
  89.                 byte[] buf = jedis.get("api:key".getBytes());  
  90.                 if(buf==null){  
  91.                     return false;  
  92.                 }  
  93.                 key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();  
  94.             }  
  95.             Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody().getSubject().equals(appId);  
  96.             return true;  
  97.         } catch (Exception e) {  
  98. //            logger.error("ApiService", "verifyToken", key, e);  
  99.             return false;  
  100.         } finally {  
  101.             JedisUtils.returnResource(jedis);  
  102.         }  
  103.     }  
  104.   
  105.     /** 
  106.      * 获取token 
  107.      * @param appId 
  108.      * @return 
  109.      */  
  110.     public String getToken(String appId) {  
  111.         Jedis jedis = null;  
  112.         try {  
  113.             jedis = JedisUtils.getResource();  
  114.             return jedis.get(at+appId);  
  115.         } catch (Exception e) {  
  116. //            logger.error("ApiService", "getToken", e);  
  117.             return "";  
  118.         } finally {  
  119.             JedisUtils.returnResource(jedis);  
  120.         }  
  121.     }  
  122. }  


spring aop配置 

[html] view plain copy
 
  1. <!--aop -->  
  2. <!--      扫描注解bean -->  
  3. <context:component-scan base-package="com.thinkgem.jeesite.common.aspect"/>  
  4. <aop:aspectj-autoproxy proxy-target-class="true"/>  



验证权限方法使用 直接用注解就可以了AccessToken

例如

 

[java] view plain copy
 
    1. package com.thinkgem.jeesite.modules.app.web.pay;  
    2.   
    3. import com.alibaba.fastjson.JSON;  
    4. import com.thinkgem.jeesite.common.annotation.AccessToken;  
    5. import com.thinkgem.jeesite.common.base.ResultApp;  
    6. import com.thinkgem.jeesite.modules.app.service.pay.AppAlipayConfService;  
    7. import org.springframework.beans.factory.annotation.Autowired;  
    8. import org.springframework.stereotype.Controller;  
    9. import org.springframework.web.bind.annotation.RequestMapping;  
    10. import org.springframework.web.bind.annotation.RequestMethod;  
    11. import org.springframework.web.bind.annotation.ResponseBody;  
    12.   
    13. import java.util.HashMap;  
    14. import java.util.Map;  
    15.   
    16. /** 
    17.  * 支付接口 
    18.  * Created by Hamming on 2016/12/27. 
    19.  */  
    20. @Controller  
    21. @RequestMapping(value = "/app/pay")  
    22. public class AppPayModule {  
    23.   
    24.     @Autowired  
    25.     private AppAlipayConfService appAlipayConfService;  
    26.   
    27.     @RequestMapping(value = "/alipay", method = RequestMethod.POST, produces="application/json")  
    28.     @AccessToken  
    29.     @ResponseBody  
    30.     public Object alipay(String orderId){  
    31.         if(orderId ==null){  
    32.             Map re = new HashMap<>();  
    33.             re.put("result",3);  
    34.             re.put("msg","参数错误");  
    35.             String json = JSON.toJSONString(re);  
    36.             return json;  
    37.         }else {  
    38.             return null;  
    39.         }  
    40.     }  
    41. }  

方法二: MVC拦截器

服务器:

拼接token之外所有参数,最后拼接token_key,做MD5,与token参数比对

如果token比对失败返回状态码 500

 

[java] view plain copy
 
  1. public class APIInterceptor extends HandlerInterceptorAdapter {  
  2.   
  3.     @Override  
  4.     public boolean preHandle(HttpServletRequest request,  
  5.             HttpServletResponse response, Object handler) throws Exception {  
  6.         Log.info(request);  
  7.           
  8.         String token = request.getParameter("token");  
  9.           
  10.         // token is not needed when debug  
  11.         if(token == null) return true;  // !! remember to comment this when deploy on server !!  
  12.           
  13.         Enumeration paraKeys = request.getParameterNames();  
  14.         String encodeStr = "";  
  15.         while (paraKeys.hasMoreElements()) {  
  16.             String paraKey = (String) paraKeys.nextElement();  
  17.             if(paraKey.equals("token"))   
  18.                 break;  
  19.             String paraValue = request.getParameter(paraKey);  
  20.             encodeStr += paraValue;  
  21.         }  
  22.         encodeStr += Default.TOKEN_KEY;  
  23.         Log.out(encodeStr);  
  24.           
  25.         if ( ! token.equals(DigestUtils.md5Hex(encodeStr))) {  
  26.             response.setStatus(500);  
  27.             return false;  
  28.         }  
  29.           
  30.         return true;  
  31.     }  
  32.   
  33.     @Override  
  34.     public void postHandle(HttpServletRequest request,  
  35.             HttpServletResponse response, Object handler,  
  36.             ModelAndView modelAndView) throws Exception {  
  37.         Log.info(request);  
  38.     }  
  39.   
  40.     @Override  
  41.     public void afterCompletion(HttpServletRequest request,  
  42.             HttpServletResponse response, Object handler, Exception ex)  
  43.             throws Exception {  
  44.           
  45.     }  
  46. }  


spring-config.xml配置中加入

[html] view plain copy
 
  1. <mvc:interceptors>  
  2.     <mvc:interceptor>  
  3.         <mvc:mapping path="/api/*" />  
  4.         <bean class="cn.web.interceptor.APIInterceptor" />  
  5.     </mvc:interceptor>  
  6. </mvc:interceptors>  

 

 

 

客户端:

拼接请求接口的所有参数,最后拼接token_key,做MD5,作为token参数

请求样例:http://127.0.0.1:8080/interface/api?key0=param0&key1=param1&token=md5(concat(param0, param1))

 
api测试页面,用到了Bootstrap和AngularJS,还有一个js的hex_md5函数
[html] view plain copy
 
  1. <!doctype html>  
  2. <html ng-app>  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <title>API test</title>  
  6.     <link href=http://www.mamicode.com/"../css/bootstrap.min.css" rel="stylesheet">  
  7.     <script src=http://www.mamicode.com/"../js/md5.min.js"></script>  
  8.     <script src=http://www.mamicode.com/"../js/angular.min.js"></script>  
  9.     <script>  
  10.         function API(url){  
  11.             this.url = arguments[0];  
  12.             this.params = Array.prototype.slice.call(arguments, 1, arguments.length);  
  13.             this.request = function(params){  
  14.                 var addr = url;  
  15.                 var values = Array.prototype.slice.call(arguments, 1, arguments.length);  
  16.                 if(params[0] != undefined && values[0] != undefined && values[0] != ‘‘)  
  17.                     addr += ‘?‘ + params[0] + "=" + values[0];  
  18.                 for(var i=1; i values.length; i++)  
  19.                     if(params[i] != undefined && values[i] != undefined && values[i] != ‘‘)  
  20.                         addr += "&" + params[i] + "=" + values[i];  
  21.                 return addr;  
  22.             }  
  23.         }  
  24.           
  25.         function APIListCtrl($scope) {  
  26.             $scope.md5 = hex_md5;  
  27.             $scope.token_key = "9ae5r06fs8";  
  28.             $scope.concat = function(){  
  29.                 var args = Array.prototype.slice.call(arguments, 0, arguments.length);  
  30.                 args.push($scope.token_key);  
  31.                 return args.join("");  
  32.             }  
  33.               
  34.             $scope.apilist = [  
  35.               
  36.             new API("account/login", "username", "pwd"),  
  37.             new API("account/register", "username", "pwd", "tel", "code"),  
  38.               
  39.             ] ;  
  40.         }  
  41.     </script>  
  42. </head>  
  43. <body>  
  44.   
  45.     <div ng-controller="APIListCtrl">  
  46.         <div> Search: <input type="text" ng-model="search"><hr>  
  47.         token_key <input type="text" ng-model="token_key">  
  48.         md5 <input type="text" ng-model="str"> {{md5(str)}}  
  49.         </div>  
  50.         <hr>  
  51.         <div ng-repeat="api in apilist | filter:search" >  
  52.             <form action="{{api.url}}" method="post">  
  53.             <href=http://www.mamicode.com/"{{api.request(api.params, value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}">  
  54.             {{api.request(api.params, value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}  
  55.             </a>  
  56.             <br>  
  57.             {{concat(value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}  
  58.             <br>  
  59.             {{api.params[0]}} <input id="{{api.params[0]}}" name="{{api.params[0]}}" ng-model="value0" ng-hide="api.params[0]==undefined">  
  60.             {{api.params[1]}} <input id="{{api.params[1]}}" name="{{api.params[1]}}" ng-model="value1" ng-hide="api.params[1]==undefined">  
  61.             {{api.params[2]}} <input id="{{api.params[2]}}" name="{{api.params[2]}}" ng-model="value2" ng-hide="api.params[2]==undefined">  
  62.             {{api.params[3]}} <input id="{{api.params[3]}}" name="{{api.params[3]}}" ng-model="value3" ng-hide="api.params[3]==undefined">  
  63.             {{api.params[4]}} <input id="{{api.params[4]}}" name="{{api.params[4]}}" ng-model="value4" ng-hide="api.params[4]==undefined">  
  64.             {{api.params[5]}} <input id="{{api.params[5]}}" name="{{api.params[5]}}" ng-model="value5" ng-hide="api.params[5]==undefined">  
  65.             {{api.params[6]}} <input id="{{api.params[6]}}" name="{{api.params[6]}}" ng-model="value6" ng-hide="api.params[6]==undefined">  
  66.             {{api.params[7]}} <input id="{{api.params[7]}}" name="{{api.params[7]}}" ng-model="value7" ng-hide="api.params[7]==undefined">  
  67.             {{api.params[8]}} <input id="{{api.params[8]}}" name="{{api.params[8]}}" ng-model="value8" ng-hide="api.params[8]==undefined">  
  68.             {{api.params[9]}} <input id="{{api.params[9]}}" name="{{api.params[9]}}" ng-model="value9" ng-hide="api.params[9]==undefined">  
  69.             token <input id="token" name="token" value=http://www.mamicode.com/"{{md5(concat(value0, value1, value2, value3, value4, value5, value6, value7, value8, value9))}}">  
  70.             <input type="submit" class="btn" ng-hide="api.params[0]==undefined">  
  71.             </form>  
  72.             <hr>  
  73.         </div>  
  74.     </div>  
  75.   
  76. </body>  
  77. </html>  

Java 两种方式实现Token校验