Token验证实现-JAVA

来源:互联网 发布:徐老师淘宝外设店 编辑:程序博客网 时间:2024/06/07 05:28

前言:上一篇JWT-TOKEN博客有详细介绍JWT TOKEN的原理机制,这篇博文主要是具体实现。


Token主要是用于以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上密匙。

1、Token工具类

package com.franz.websocket;import com.franz.common.utils.StringUtils;import com.franz.weixin.p3.oauth2.util.MD5Util;import io.jsonwebtoken.*;import net.sf.json.JSONObject;import org.apache.commons.codec.binary.Base64;import org.jeecgframework.core.common.service.CommonService;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletResponse;import javax.xml.bind.DatatypeConverter;import java.util.Date;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;/** * OAuthTokenUtils * Token管理 * @author nizhigengvip@163.com * @version 2017-08-01 */public class OAuthTokenManager {    private String APP_ID = "";    private String APP_SECRET = "";    private String KEY_SING =  ""; //用於存放TOKEN的標誌,Redis    private LinkedHashMap<String, Object> pairs = new LinkedHashMap();//封装json的map    private CommonService service;    public static final int MINUTE_TTL = 60*1000;  //millisecond    public static final int HOURS_TTL = 60*60*1000;  //millisecond    public static final int DAY_TTL = 12*60*60*1000;  //millisecond    private OAuthTokenManager() {}    private static OAuthTokenManager single=null;    public static OAuthTokenManager getInstance() {            if (single == null) {                single = new OAuthTokenManager();            }            return single;        }    public String getKEY_SING() {        return KEY_SING;    }    public void setPairs(LinkedHashMap<String, Object> pairs) {        this.pairs = pairs;    }    public LinkedHashMap<String, Object> getPairs() {        return pairs;    }    public void put(String key, Object value){//向json中添加属性,在js中访问,请调用data.map.key        pairs.put(key, value);    }    public void remove(String key){        pairs.remove(key);    }    /**     * 總體封裝     * @param appid     * @param secret     * @param logicInterface 回調函數     * @return     */    public String token(String appid,String secret,LogicInterface logicInterface){        //获取appid和secret        this.accessPairs(appid,secret);        //验证appid和secretS,获取对象载体        Object subject = this.loginAuthentication(logicInterface);        //生成JWT签名数据ToKen        String token = this.createToken(this.generalSubject(subject),this.MINUTE_TTL);        return token;    }    public void accessPairs(String APP_ID, String APP_SECRET) {        this.APP_ID = APP_ID;        this.APP_SECRET = APP_SECRET;        //this.KEY_SING = MD5Util.MD5Encode(APP_ID+"_"+APP_SECRET, "UTF-8").toUpperCase();//要用到的时候才用    }    public Object loginAuthentication(LogicInterface logicInterface){        if (StringUtils.isNotBlank(APP_ID) && StringUtils.isNotBlank(APP_SECRET)) {                Map<String, Object> map = new HashMap<>();                map.put("APP_ID",APP_ID);                map.put("APP_SECRET",APP_SECRET);                if(logicInterface == null || logicInterface.handler(map) == null){                    return map;                }else {                    return logicInterface.handler(map);                }        } else {            return null;        }    }    /**     * 由字符串生成加密key     * @return     */    public SecretKey generalKey(){        String stringKey = APP_ID+APP_SECRET;        byte[] encodedKey = Base64.decodeBase64(stringKey);        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");        return key;    }    /**     * 生成subject信息     * @param obj     * @return     */    public static String generalSubject(Object obj){        if(obj != null ) {            JSONObject json = JSONObject.fromObject(obj);            return json.toString();        }else{            return "{}";        }    }    /**     * 创建token     * @param subject     * @param ttlMillis     * @return     * @throws Exception     */    public String createToken(String subject, long ttlMillis) {        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;        long nowMillis = System.currentTimeMillis();        Date now = new Date(nowMillis);        SecretKey key = generalKey();        JwtBuilder builder = Jwts.builder()                .setId(APP_ID)                .setIssuedAt(now)                .setSubject(subject)                .signWith(signatureAlgorithm, key);        if (ttlMillis >= 0) {            long expMillis = nowMillis + ttlMillis;            Date exp = new Date(expMillis);            builder.setExpiration(exp);        }        return builder.compact();    }    /**     * 解密token     * @param token     * @return     * @throws Exception     */    public Claims validateToken(String token) throws Exception{        Claims claims = Jwts.parser()                .setSigningKey(generalKey())                .parseClaimsJws(token).getBody();        /*System.out.println("ID: " + claims.getId());        System.out.println("Subject: " + claims.getSubject());        System.out.println("Issuer: " + claims.getIssuer());        System.out.println("Expiration: " + claims.getExpiration());*/        return claims;    }}

2、业务逻辑接口

public interface LogicInterface { //其实这个接口,主要用于回调函数,如果不考虑用也可以    /**     * 處理業務     * @param map     */    public Map<String, Object> handler(Map<String, Object> map);}


3、ControllerWeb
import com.ewider.weixin.p3.oauth2.util.MD5Util;import io.jsonwebtoken.Claims;import io.jsonwebtoken.ExpiredJwtException;import io.jsonwebtoken.MalformedJwtException;import io.jsonwebtoken.SignatureException;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * OAuthTokenController * * @author Franz.ge.倪志耿 * @version 2017-08-01 */@Scope("prototype")@Controller@RequestMapping("/oAuthToken")public class OAuthToken {    /**     * 獲取Token     * @param grant_type     * @param appid     * @param secret     * @return     */    @RequestMapping(params = "token",method = RequestMethod.GET)    @ResponseBody    public Object token (@RequestParam(value = "grant_type") String grant_type, @RequestParam(value = "appid") String appid,            @RequestParam(value = "secret") String secret,HttpServletResponse response) {        Map<String, Object> map = new HashMap<>();        switch (grant_type) {            case "authorization_code" : //授权码模式(即先登录获取code,再获取token)                break;            case "password" : //密码模式(将用户名,密码传过去,直接获取token)                break;            case "client_credentials" : //客户端模式(无用户,用户向客户端注册,然后客户端以自己的名义向’服务端’获取资源)                OAuthTokenManager oAuthTokenManager = OAuthTokenManager.getInstance();                String token = oAuthTokenManager.token(appid, secret,null);//loginInterface是业务逻辑回掉函数                //返回Token                map.put("access_token",token);                map.put("expires_in",OAuthTokenManager.MINUTE_TTL/1000);                break;            case "implicit" : //简化模式(在redirect_uri 的Hash传递token; Auth客户端运行在浏览器中,如JS,Flash)                break;            case "refresh_token" : //刷新access_token                break;        }        return map;    }    @RequestMapping(params = "loginAuth2",method = RequestMethod.GET)    @ResponseBody    public Object loginAuth2 (HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "accessToken") String accessToken ){        Map<String, Object> map = new HashMap<>();        //COOKIE不存在:解析验证正确性        try {                OAuthTokenManager oAuthTokenManager = OAuthTokenManager.getInstance();                Claims claims = oAuthTokenManager.validateToken(accessToken);                if (claims != null ) {                    map.put("state","success");                    map.put("loginAuth","采用Token登录");                    int validMillis = (int)(claims.getExpiration().getTime()-System.currentTimeMillis());                    if(validMillis > 0) {                        //交給容器管理,可以存放redis,這裡模擬是cookie                        Cookie cookie = new Cookie(MD5Util.MD5Encode("MD5SING", "UTF-8").toUpperCase(), accessToken);                        cookie.setMaxAge(validMillis/1000);                        response.addCookie(cookie);                    }                }else{                    map.put("state","fail");                }            }catch (MalformedJwtException | SignatureException e){                     map.put("state","signature");//改造簽名,或者無效的Token                     map.put("loginAuth","該Token無效");//改造簽名,或者無效的Token            }catch (ExpiredJwtException e){                     map.put("state","expired");//改造簽名,或者無效的Token                     map.put("loginAuth","Token已經過時");            }catch (Exception e) {            e.printStackTrace();            map.put("state","fail");            }            return map;    }    @RequestMapping(params = "index",method = RequestMethod.GET)    @ResponseBody    public Object index (HttpServletRequest request, HttpServletResponse response){        Map<String, Object> map = new HashMap<>();        //从COOKIE中查找,模拟访问,可以集成容器管理        Cookie[] cookies = request.getCookies();        if (cookies!=null) {            for (int i = cookies.length-1; i >= 0; i--) {                Cookie cookie = cookies[i];                if (cookie.getName().equals(MD5Util.MD5Encode("MD5SING", "UTF-8").toUpperCase())) {                    //跳过登陆                    map.put("index","采用Redis登录");                    return map;                }            }        }        map.put("index","你的Token已经销毁");        return map;    }}


4、加入jar包,里面有MD5.jar(这个网上博客各有实现也有jar,自行导入下载)

     重点然后加入JJWT-0.7.0.jar

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency>

总结:如果不清楚JWT TOKEN的原理机制,我的上一篇JWT-TOKEN博客有详细介绍,这篇博文主要是具体实现。

原创粉丝点击