簡單使用java+token

文章簡介

  • 最近公司的一款app需要提供token的令牌驗證。本人在使用之後總結一些經驗讓後來之人更快的掌握這一技術。
    什麼是token,簡單來說token就相當於酒店的門卡。在門卡的有效期內可以打開該酒店的一間房間。轉回java,酒店相當於我們的後臺方法,token相當於門卡,在token的有效期內可以訪問後臺中的任意方法。*

話不多說先附代碼

 //首先定義一下DES
         DesUtils des = new DesUtils("leemenz"); //自定義密鑰

        @RequestMapping(value = "getUserNameBYword", method = RequestMethod.GET)
		@ResponseBody
		public InterfaceUtil<Userinfo> getuserinfo(@RequestParam(value="username")String username,@RequestParam(value="userword")String userword) throws Exception{
			//定義fs爲格式化時間
			SimpleDateFormat fs = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
			//定義date爲當前系統日期
			Date date = new Date();
			//定義Userinfo的泛型list集合
			List<Userinfo> list = null;
			//定義返回碼
			int rcode = 0;
			//定義返回內容
			String rmessage = "";
			//根據用戶名密碼查詢該用戶
			Userinfo user=userinfoservice.getUserNameBYword(username, userword);	
			//判斷user是否爲null
			if(user!=null){
			//判斷是否存在token,第一次登陸無token即創建token賦給用戶
			if(user.getToken().equals("")){
				//token 由時間戳的形式拼接而成,對生成的token執行des加密
				String token = des.encrypt(fs.format(date));
				user.setToken(token);
				//執行修改用戶方法,爲首次登陸的用戶創建token令牌
				userinfoservice.updateUserinfoBytoken(user);
			}else{
				//如果用戶存在token,證明該用戶不是首次登陸。
				//通過des的解密方法獲得正常的token值
				String jmtoken = des.decrypt(user.getToken());
				//將舊時間轉換爲date類型
				Date d1 = fs.parse(jmtoken);
				//將新時間轉換爲date類型
				Date d2 = fs.parse(fs.format(date));
				//新時間減去舊時間獲得兩個日期之間的時間差,除以1000獲得相差的秒數
				long diff = (d2.getTime() - d1.getTime())/1000;
				//對diff進行判斷,86400即爲一天24小時的秒數
				//如果diff小於86400證明已經過期,爲rcode賦值201,爲rmessage賦值 “認證權限已過期”,向前臺返回
				if(diff>86400){
					rcode = 201;
					rmessage = "認證權限已過期";
					//發送之前將改用戶數據庫中的token抹除,只需該用戶再次重新登錄即可拿到新的token令牌
					user.setToken("");
					userinfoservice.updateUserinfoBytoken(user);
					return  new InterfaceUtil<Userinfo>(rcode,rmessage,list);
				}
			}
			list = new ArrayList<Userinfo>();
			//向該泛型list集合中添加user
			list.add(user);
			//判斷list的size是否爲0,爲0表示該list爲空
			if(list.size() != 0){
				rcode = 200;
				rmessage = "正常應答";
			}else{
				rcode = 9001;
				rmessage = "系統錯誤";
			}
			return  new InterfaceUtil<Userinfo>(rcode,rmessage,list);
			}else{
				//如果爲null直接返回該狀態碼
				rcode = 9002;
				rmessage = "用戶名或密碼錯誤";
				return  new InterfaceUtil<Userinfo>(rcode,rmessage,list);
			}
		}

其中用到了DES的加密方法

package com.sanfan.utils;
import java.security.Key;

import javax.crypto.Cipher;

/**
 * 使用DES算法對字符串進行加密解密 (加密解密的操作步驟正好相反, 參考 {@link #encrypt(String)}, {@link #decrypt(String)})
 */
public class DesUtils {
    private static String defaultSecretKey = "default_secret_key"; //默認密鑰
    private Cipher encryptCipher = null; //加密器
    private Cipher decryptCipher = null; //解密器

    public DesUtils() throws Exception {
        this(defaultSecretKey);
    }

    /**
     * @param secretKey 加密解密使用的密鑰
     */
    public DesUtils(String secretKey) {
        Key key;
        try {
            key = getKey(secretKey.getBytes());
            encryptCipher = Cipher.getInstance("DES");
            encryptCipher.init(Cipher.ENCRYPT_MODE, key);
            decryptCipher = Cipher.getInstance("DES");
            decryptCipher.init(Cipher.DECRYPT_MODE, key);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加密 (邏輯: 1. 將要加密的字符串轉換爲字節數組(byte array)<br/>
     *            2. 將第一步的字節數組作爲輸入使用加密器(Cipher)的doFinal方法進行加密, 返回字節數組<br/>
     *            3. 把加密後的字節數組轉換成十六進制的字符串)<br/>
     * @param strIn 要加密的字符串
     * @return 返回加密後的十六進制字符串
     * @throws Exception
     */
    public String encrypt(String strIn) throws Exception {
        return byteArr2HexStr(encrypt(strIn.getBytes()));
    }

    public byte[] encrypt(byte[] arrB) throws Exception {
        return encryptCipher.doFinal(arrB);
    }

    /**
     * 解密 (邏輯: 1. 把加密後的十六進制字符串轉換成字節數組(byte array)<br/>
     *            2. 將第一步的字節數組作爲輸入使用加密器(Cipher)的doFinal方法進行解密, 返回字節數組(byte array)<br/>
     *            3. 把解密後的字節數組轉換成字符串)<br/>
     * @param strIn
     * @return
     * @throws Exception
     */
    public String decrypt(String strIn) throws Exception {
        return new String(decrypt(hexStr2ByteArr(strIn)));
    }

    public byte[] decrypt(byte[] arrB) throws Exception {
        return decryptCipher.doFinal(arrB);
    }

    public static String byteArr2HexStr(byte[] arrB) throws Exception {
        int iLen = arrB.length;
        // 每個byte用兩個字符才能表示,所以字符串的長度是數組長度的兩倍
        StringBuffer sb = new StringBuffer(iLen * 2);
        for (int i = 0; i < iLen; i++) {
            int intTmp = arrB[i];
            // 把負數轉換爲正數
            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }
            // 小於0F的數需要在前面補0
            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16));
        }
        return sb.toString();
    }

    public static byte[] hexStr2ByteArr(String strIn) throws Exception {
        byte[] arrB = strIn.getBytes();
        int iLen = arrB.length;
        // 兩個字符表示一個字節,所以字節數組長度是字符串長度除以2
        byte[] arrOut = new byte[iLen / 2];
        for (int i = 0; i < iLen; i = i + 2) {
            String strTmp = new String(arrB, i, 2);
            arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
        }
        return arrOut;
    }

    private Key getKey(byte[] arrBTmp) throws Exception {
        // 創建一個空的8位字節數組(默認值爲0)
        byte[] arrB = new byte[8];
        // 將原始字節數組轉換爲8位
        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }
        // 生成密鑰
        Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
        return key;
    }


    /**
     * 用法實例
     */
    public static void main(String[] args) {
        try {
            String test = "liwc";
            //注意這裏,自定義的加密的KEY要和解密的KEY一致,這就是鑰匙,如果你上鎖了,卻忘了鑰匙,那麼是解密不了的
            DesUtils des = new DesUtils("leemenz"); //自定義密鑰
            System.out.println("加密前的字符:" + test);
            System.out.println("加密後的字符:" + des.encrypt(test));
            System.out.println("解密後的字符:" + des.decrypt(des.encrypt(test)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

最後我們在攔截器裏寫攔截一下就可以了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章