1. 程式人生 > >關於app介面呼叫時如何使session和token票據來保證介面呼叫的安全

關於app介面呼叫時如何使session和token票據來保證介面呼叫的安全

傳統的http請求時無狀態的。及一個使用者向伺服器端傳送請求時,當再次傳送請求時不能判斷是同一個使用者傳送 的請求,及無法記錄使用者資訊。

Session是指一個終端使用者與互動系統進行通訊的時間間隔,通常指從註冊進入系統到登出退出系統之間所經過的時間也成為會話時間。

token是有後端加密產生的一段加密字元。app訪問介面是的票據。

1.關於token域session之間的關聯關係
 1-1.token和session必須存在否則介面無法呼叫
 1-1  1.使用者A登陸--客戶端A
 1-1  2.使用者A 登陸---客戶端B時 1.首先判斷記憶體中是否存在token(通過賬號名稱查詢)
         存在:給客戶端B一個提示資訊 --然後傳送一個請求清空客戶端A產生的session和token,
         然後重新登陸,產生新的token。
         不存在:直接登陸沒有二次回撥請求過程。
 1.當用戶請求介面是:邏輯判斷如下
   1.從session中取出當前會話的物件 ---
       會話存在 -
          1.解析token獲取獲取accesstoken物件
          2.判斷當合會話的sessionid和記憶體中的session是否一致
          3.判斷當前的accesstoken是否失效
          4.判斷會話中的使用者和當前的accesstoken是否一致。

         5.當以上條件都滿足是,在進行許可權判斷是否有許可權呼叫當前請求的資源。

程式碼如下

   1.Accesstoken類如下

/**
 * app票據訪問的憑證
 * @author Administrator
 *
 */
public class AccessToken {
	private String signature;// 簽名  
    
    private String timestamp;// 時間戳  
    /*sessionid*/  
    private String sessionId;
    private String random;// 隨機數  

	public String getRandom() {
		return random;
	}

	public void setRandom(String random) {
		this.random = random;
	}

	public String getSignature() {
		return signature;
	}

	public void setSignature(String signature) {
		this.signature = signature;
	}

	public String getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(String timestamp) {
		this.timestamp = timestamp;
	}

	public String getSessionId() {
		return sessionId;
	}

	public void setSessionId(String sessionId) {
		this.sessionId = sessionId;
	}

	@Override
	public String toString() {
		return "signature="+signature+"×tamp="+timestamp+"&sessionId="+sessionId+"&random="+random;
	}
    
}
2TokenUtill工具如下
public class TokenUtil {
	private static ConcurrentHashMap<String, AccessToken> map = new ConcurrentHashMap<String, AccessToken>();


	/**
	 * 生成加密Token
	 * 
	 * @param username
	 * @return
	 */
	public static AccessToken generateAccessToken(String username,
			String sessionId) {
		AccessToken accessToken = new AccessToken();
		// 設定簽名
		accessToken.setSignature(username);
		// 設定時間戳
		accessToken.setTimestamp(getTimeStamp());
		// 設定sessionId
		accessToken.setSessionId(sessionId);
		// 設定授權碼
		accessToken.setRandom(getRandom());
		return accessToken;
	}


	/**
	 * 【重新生成】更新Token
	 * 
	 * @param token
	 * @return
	 */
	public static String reCreateToken(String token) {


		return null;
	}


	/**
	 * 設定token 
	 * @param username
	 * @param userToken
	 */
	public static void putToken(String username, AccessToken accessToken) {
		map.put(username, accessToken);
	}


	/**
	 * 判定是否已經登入
	 * 
	 * @param signature
	 * @return
	 */
	public static boolean hasLogin(String signature) {
		if (map.containsKey(signature)) {
			return true;
		}
		return false;
	}
	/**
	 * 清空token
	 * 
	 * @param signature
	 * @return
	 */
	public static void removeToken(String signature) {
		 map.remove(signature);
	}
	/**
	 * 獲取accesstoken物件
	 * 
	 * @param signature
	 * @return
	 */
	public static AccessToken getAccessToken(String signature) {
		return map.get(signature);


	}


	/**
	 * 加密簽名
	 * 
	 * @param encrypt
	 * @return
	 * @throws Exception
	 */
	public static String encryptSignature(AccessToken token)
			throws Exception {
		return PBECoder.encrypt(token.toString(), PBECoder.PWD, PBECoder.salt);
	}


	/**
	 * 加密簽名
	 * 
	 * @param encrypt
	 * @return
	 * @throws Exception
	 */
	public static String encryptSignature(String username, String sessionId,
			byte[] salt) throws Exception {
		AccessToken token = generateAccessToken(username, sessionId);
		return PBECoder.encrypt(token.toString(), PBECoder.PWD, salt);
	}


	/**
	 * 解密簽名
	 * 
	 * @param signature
	 * @return
	 * @throws Exception
	 */
	public static String decryptSignature(String encryptToken, byte[] salt)
			throws Exception {
		return PBECoder.decryptString(encryptToken, PBECoder.PWD, salt);
	}


	/**
	 * 解密簽名
	 * 
	 * @param signature
	 * @return
	 * @throws Exception
	 */
	public static String decryptSignature(String encryptToken) throws Exception {
		return PBECoder
				.decryptString(encryptToken, PBECoder.PWD, PBECoder.salt);
	}


	/**
	 * 生成時間戳
	 * 
	 * @return
	 */
	public static String getTimeStamp() {
		return Calendar.getInstance().getTimeInMillis() + "";
	}


	/**
	 * 生成隨機數
	 * 
	 * @return
	 */
	public static String getRandom() {
		return new Random().nextInt(999999999) + "";
	}


	/**
	 * 解析加密使用者Token
	 * 
	 * @param token
	 * @return
	 * @throws Exception
	 */
	public static AccessToken decryptToken(String encyptToken) throws Exception {


		String[] params = decryptSignature(encyptToken).split("&");
		// 分析使用者提交過來的Token
		AccessToken accessToken = new AccessToken();
		for (int i = 0, j = params.length; i < j; i++) {
			String[] currentParams = params[i].split("=");
			String param = currentParams[0];
			if ("signature".equals(param)) {
				accessToken.setSignature(currentParams[1]);
			} else if ("timestamp".equals(param)) {
				accessToken.setTimestamp(currentParams[1]);
			} else if ("sessionId".equals(param)) {
				accessToken.setSessionId(currentParams[1]);
			}
		}
		return accessToken;
	}


	/**
	 * 驗證token的失效性
	 * 
	 * @param timestampStr
	 *            時間戳
	 * @return
	 * @throws Exception
	 */
	public static boolean verifyAccessToken(String timestampStr)
			throws Exception {
		// 驗證是否存在此使用者登入的Token
		if (timestampStr != null) {
			// 判定時間戳是否過期
			long currentTime = Calendar.getInstance().getTimeInMillis();
			long timestamp = Long.valueOf(timestampStr);
			// Token有效時間為60分鐘
			long verifyTime = 60 * 60 * 1000;
			if (currentTime - timestamp > verifyTime) {
				return true;
			}
			return false;
		}
		return true;
	}

3.在攔截器中攔截呼叫介面的請求
/**
 * 跨域攔截器 --主要功能 獲取會話資訊和token--通過token解析成accesstoken物件--對使用者進行許可權判斷以及token的失效性判斷
 * 
 * @author wjb
 * @version 1.0.0 2016.8
 */


public class CrossInterceptor extends HandlerInterceptorAdapter {
	@Override
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
		String token = ""; /* app介面票據 */
		String errcode ="0" ; /*返回的狀態碼*/
		String errmsg = ""; /* 介面呼叫失敗是返回給客戶端的提示資訊 */
		Enumeration e = request.getHeaders("X-CSRF-TOKEN");/* 從請求的header中獲取token */
		while (e.hasMoreElements()) {
			token = (String) e.nextElement();
		}
		HttpSession session =  request.getSession();
		Object temp = session.getAttribute(ProperHelper.SESSION_KEY);/* 獲取當前會話的使用者 */
		/* token字串解析成accesstoken物件對該物件進行驗證 */
		if (token != null && !token.isEmpty() && temp != null) {
			Member member =(Member)temp;
			token = java.net.URLDecoder.decode(token, "UTF-8");
			AccessToken accessToken = TokenUtil.decryptToken(token);
			// 驗證是否存在此使用者登入的Token
			if (accessToken != null) {
				/*session是否一致*/
				if(!TokenUtil.getAccessToken(accessToken.getSignature()).getSessionId().equals(accessToken.getSessionId())){
					errcode="113";
					errmsg ="session異常請重新登陸";
				}// 判定時間戳是否過期,
				else if (TokenUtil.verifyAccessToken(accessToken.getTimestamp())) {
					errcode="111";
					errmsg = "token已失效,請重新登陸";
				}
				/* 驗證登陸的使用者和token解析出來的使用者是否一致 */
				else if (!accessToken.getSignature().equals(member.getLoginName())) {
					errcode ="112";
					errmsg = "token被篡改";
				} else {
					/* token驗證通過後下一步1.對請求訪問的地址進行許可權攔截 */
				}
			} else {
				errcode ="114";
				errmsg = "無效的token";
			}
		} else {
			errcode ="114";
			errmsg = "session失效";
		}
		if (!errmsg.isEmpty()) {
			/*異常時清空session*/
			session.invalidate();
		   JsonUtils.response(errcode ,errmsg, request, response);
			return false;
		}
		return super.preHandle(request, response, handler);
	}


}


相關推薦

關於app介面呼叫如何使sessiontoken票據保證介面呼叫安全

傳統的http請求時無狀態的。及一個使用者向伺服器端傳送請求時,當再次傳送請求時不能判斷是同一個使用者傳送 的請求,及無法記錄使用者資訊。 Session是指一個終端使用者與互動系統進行通訊的時間間隔,通常指從註冊進入系統到登出退出系統之間所經過的時間也成為會話時間。 to

sessiontoken區別

獲取 session 校驗 返回 查詢 字符 無法 憑證 真的 分布式系統認證/授權目前分布式系統存在兩種常用的認證授權方式:分布式session和token 1.session的概念 session中存放登錄用戶的個人信息,創建session時,隨機生成一個sessio

cookie、sessiontoken

aio 一個用戶 核心 選擇 uil img 做的 它的 blank https://zhuanlan.zhihu.com/p/25495290?utm_source=wechat_session&utm_medium=social 一、cookie   眾所周

小白必讀:閑話HTTP短連接中的SessionToken

caption 之路 1年 機制 視頻 挑戰 tps 每一個 負載 本文引用了劉欣的文章,感謝原作者的分享。 1、引言 Http協議在現今主流的IM系統中擁有無可替代的重要性(在IM系統中用HTTP發起的連接被大家簡稱為http短連接),但Http作為傳統互聯網信息交換技術

使用者資訊認證sessiontoken

在進行使用者資訊認證之前,我們需要先知道兩個知識點: (1):http是無狀態協議。所以,在進行資訊認證時,我們需要引入狀態機制,也就是session機制。 (2):cookie,與域名有關,域名不變,cookie不變。也就是說,在同一域名下,請求各種資源都會攜帶cookie回後端。 下面來談談兩種認證

IM開發基礎知識補課(四):正確理解HTTP短連線中的Cookie、SessionToken

1、前言 眾所周之,IM是個典型的快速資料流交換系統,當今主流IM系統(尤其移動端IM)的資料流交換方式都是Http短連線+TCP或UDP長連線來實現。Http短連線主要用於從伺服器讀取各種持久化資訊:比如使用者資訊、聊天曆史記錄、好友列表等等,長連線則是用於實時的聊天訊息

cookie、sessiontoken區別

cookie 和 session 眾所周知,HTTP 是一個無狀態協議,所以客戶端每次發出請求時,下一次請求無法得知上一次請求所包含的狀態資料,如何能把一個使用者的狀態資料關聯起來呢? 比如在淘寶的某個頁面中,你進行了登陸操作。當你跳轉到商品頁時,服務端如何知道你是已經登

sessiontoken實現使用者認證的異同

現在貌似大多數網站使用者認證都是基於 session 的,即在服務端生成使用者相關的 session 資料,而發給客戶端 sesssion_id 存放到 cookie 中,這樣用客戶端請求時帶上 session_id 就可以驗證伺服器端是否存在 session 資料,以此完成

javaEE開發中使用session同步token機制防止併發重複提交

    通常在普通的操作當中,我們不需要處理重複提交的,而且有很多方法來防止重複提交。比如在登陸過程中,通過使用redirect,可以讓使用者登陸之上重定向到後臺首頁介面,當用戶重新整理介面時就不會觸發重複提交了。或者使用token,隱藏在表單中,當提交時進行token驗證,

關於模擬登陸的小結-抓包、cookie、sessiontoken

概述 上個星期根據bcloud寫了個Java版本的登陸專案。其實本來時想做個Linux的百度雲登陸軟體,但是做到獲取bdstoken的時候出了問題解決不了。後來我把bcloud專案下了下來用發現也有問題,應該是百度登陸的過程有了一些改動。通過 web抓包找到一些線索,

Cookie、SessionToken的區別

目錄 Cookie Session認證機制 Token認證機制 Token預防CSRF Session認識和Token認證的區別 前言:HTTP是一種無狀態的協議,為了分辨連結是誰發起的,需要瀏覽器自己去解決這個問題。不然有些情況下即使是開啟同一個網站的不同頁面也

cookie、sessiontoken那些事

cookie 和 session 眾所周知,HTTP 是一個無狀態協議,所以客戶端每次發出請求時,下一次請求無法得知上一次請求所包含的狀態資料,如何能把一個使用者的狀態資料關聯起來呢? 比如在淘寶的某個頁面中,你進行了登陸操作。當你跳轉到商品頁時,服務端如何知道你是已經登陸

一篇文章弄懂cookie、sessiontoken

概念 cookie cookie儲存在客戶端,HTTP是無狀態的,HTTP每次發出的時候會附上該域名下的cookie,從而可以給HTTP附上狀態,最常見的就是登入態。 session和token session和token算是一類的,他們是兩種不同的伺服器的驗證

Cookie,SessionToken機制區別.

1.背景介紹 由於HTTP是一種無狀態協議,伺服器沒有辦法單單從網路連線上面知道訪問者的身份,為了解決這個問題,就誕生了Cookie Cookie實際上是一小段的文字資訊。客戶端請求伺服器,如果伺服器需要記錄該使用者狀態,就使用response向客戶端瀏覽器頒發一個C

session儲存token避免post重複提交

第一步,在頁面調取前,生成隨機數token   $this->session->set_userdata("token", md5(microtime(true)));   第二步,在頁面表單裡,增加一個hidden的input用來提交token   <input 

WPF Page 介面跳轉簡單框架DoubleAnimation動畫跳轉介面

介面顯示 public enum PageType { Index, Error, Copy, Wait, None } public class UICont

app與php後臺介面登入認證、驗證(seesiontoken

簡要:隨著電商的不斷髮展,APP也層次不窮,隨著科技的發展主要登入形式(微信、QQ、賬號/密碼);為此向大家分享一下"app與php後臺介面登入認證、驗證"想法和做法;希望能夠幫助困惑的夥伴們,如果有不對或者好的建議告知下;*~*!一、登入機制粗略分析:登入可分為三個階段(登

SqlAlchemy 中操作數據庫sessionscoped_session的區別

tro color war mapped 數據庫 大小 bind nes email 原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from

4月16日 python學習總結 DBUtils模塊、orm cookie、sessiontoken

用戶名 可用 繼續 打開 基於 動態 編號 身份認證 The 一、DBUtils模塊 介紹 The DBUtils suite is realized as a Python package containing two subsets of modules, one fo

微信公眾平臺申請測試介面URLTOKEN的配置,怎麼在本地讓微信能通過80埠訪問

                最近開始微信公眾平臺的搗鼓,但相信和很多新手一樣,遇到的第一件事就是如何配置url,主要是微信的8