您好,登錄后才能下訂單哦!
這篇文章主要介紹“Token登陸驗證機制怎么實現(xiàn)”,在日常操作中,相信很多人在Token登陸驗證機制怎么實現(xiàn)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Token登陸驗證機制怎么實現(xiàn)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
做過Web開發(fā)的程序員應(yīng)該對Session都比較熟悉,Session是一塊保存在服務(wù)器端的內(nèi)存空間,一般用于保存用戶的會話信息。
用戶通過用戶名和密碼登陸成功之后,服務(wù)器端程序會在服務(wù)器端開辟一塊Session內(nèi)存空間并將用戶的信息存入這塊空間,同時服務(wù)器會在cookie中寫入一個Session_id的值,這個值用于標識這個內(nèi)存空間。
下次用戶再來訪問的話會帶著這個cookie中的session_id,服務(wù)器拿著這個id去尋找對應(yīng)的session,如果session中已經(jīng)有了這個用戶的登陸信息,則說明用戶已經(jīng)登陸過了。
使用Session保持會話信息使用起來非常簡單,技術(shù)也非常成熟。但是也存在下面的幾個問題:
服務(wù)器壓力大:通常Session是存儲在內(nèi)存中的,每個用戶通過認證之后都會將session數(shù)據(jù)保存在服務(wù)器的內(nèi)存中,而當(dāng)用戶量增大時,服務(wù)器的壓力增大。
Session共享:現(xiàn)在很多應(yīng)用都是分布式集群,需要我們做額外的操作進行Session共享;
CSRF跨站偽造請求攻擊:Session機制是基于瀏覽器端的cookie的,cookie如果被截獲,用戶就會很容易受到跨站請求偽造的攻擊。
基于token的認證機制將認證信息返回給客戶端并存儲。下次訪問其他頁面,需要從客戶端傳遞認證信息回服務(wù)端。簡單的流程如下:
客戶端使用用戶名跟密碼請求登錄;
服務(wù)端收到請求,去驗證用戶名與密碼;
驗證成功后,服務(wù)端會簽發(fā)一個 Token,再把這個 Token 發(fā)送給客戶端;
客戶端收到 Token 以后可以把它存儲起來,比如放在 Cookie 里或者 Local Storage 里;
客戶端每次向服務(wù)端請求資源的時候需要帶著服務(wù)端簽發(fā)的 Token;
服務(wù)端收到請求,然后去驗證客戶端請求里面帶著的 Token,如果驗證成功,就向客戶端返回請求的數(shù)據(jù);
基于token的驗證機制,有以下的優(yōu)點:
支持跨域訪問,將token置于請求頭中,而cookie是不支持跨域訪問的;
無狀態(tài)化,服務(wù)端無需存儲token,只需要驗證token信息是否正確即可,而session需要在服務(wù)端存儲,一般是通過cookie中的sessionID在服務(wù)端查找對應(yīng)的session;
無需綁定到一個特殊的身份驗證方案(傳統(tǒng)的用戶名密碼登陸),只需要生成的token是符合我們預(yù)期設(shè)定的即可;
更適用于移動端(Android,iOS,小程序等等),像這種原生平臺不支持cookie,比如說微信小程序,每一次請求都是一次會話,當(dāng)然我們可以每次去手動為他添加cookie,詳情請查看博主另一篇博客;
避免CSRF跨站偽造攻擊,還是因為不依賴cookie;
缺點的話一個就是相比較于傳統(tǒng)的session登陸機制實現(xiàn)起來略微復(fù)雜一點,另外一個比較大的缺點是由于服務(wù)器不保存 token,因此無法在使用過程中廢止某個 token,或者更改 token 的權(quán)限。也就是說,一旦 token 簽發(fā)了,在到期之前就會始終有效,除非服務(wù)器部署額外的邏輯。
退出登陸的話,只要前端清除token信息即可。
JWT(JSON Web Token)就是基于token認證的代表,這邊就用JWT為列來介紹基于token的認證機制。
需要引入JWT的依賴
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency>
生成token和驗證token的工具類如下:
public class JWTTokenUtil { //設(shè)置過期時間 private static final long EXPIRE_DATE=30*60*100000; //token秘鑰 private static final String TOKEN_SECRET = "ZCfasfhuaUUHufguGuwu2020BQWE"; public static String token (String username,String password){ String token = ""; try { //過期時間 Date date = new Date(System.currentTimeMillis()+EXPIRE_DATE); //秘鑰及加密算法 Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); //設(shè)置頭部信息 Map<String,Object> header = new HashMap<>(); header.put("typ","JWT"); header.put("alg","HS256"); //攜帶username,password信息,生成簽名 token = JWT.create() .withHeader(header) .withClaim("username",username) .withClaim("password",password).withExpiresAt(date) .sign(algorithm); }catch (Exception e){ e.printStackTrace(); return null; } return token; } public static boolean verify(String token){ /** * @desc 驗證token,通過返回true * @params [token]需要校驗的串 **/ try { Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); JWTVerifier verifier = JWT.require(algorithm).build(); DecodedJWT jwt = verifier.verify(token); return true; }catch (Exception e){ e.printStackTrace(); return false; } } public static void main(String[] args) { String username ="name1"; String password = "pw1"; //注意,一般不會把密碼等私密信息放在payload中,這邊只是舉個列子 String token = token(username,password); System.out.println(token); boolean b = verify(token); System.out.println(b); } }
執(zhí)行結(jié)果如下:
Connected to the target VM, address: '127.0.0.1:11838', transport: 'socket' eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6IjEyMyIsImV4cCI6MTU5NzM5Nzc0OCwidXNlcm5hbWUiOiJ6aGFuZ3NhbiJ9.LI5S_nX-YcqtExI9UtKiP8FPqpQW_ccaws2coLzyOS0 true
關(guān)于DecodedJWT
這個類,大家可以重點看下,里面包含了解碼后的用戶信息。
客戶端收到服務(wù)器返回的 JWT,可以儲存在 Cookie 里面,也可以儲存在 localStorage。
此后,客戶端每次與服務(wù)器通信,都要帶上這個 JWT。你可以把它放在 Cookie 里面自動發(fā)送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求的頭信息Authorization
字段里面。
Authorization: Bearer <token>
另一種做法是,跨域的時候,JWT 就放在 POST 請求的數(shù)據(jù)體里面。
JWT 本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT 的有效期應(yīng)該設(shè)置得比較短。對于一些比較重要的權(quán)限,使用時應(yīng)該再次對用戶進行認證。
為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸。(或者是對JWT在前后端之間進行加密之后在傳輸)
上面生成JWT token的過程關(guān)鍵點就是密鑰,假如這個密鑰泄露了,那是不是就可以偽造token了。
還有就是生產(chǎn)環(huán)境的密鑰值,開發(fā)的程序員大概率是知道的,怎么防止程序要監(jiān)守自盜,偽造token值呢?希望有經(jīng)驗的大佬指教下。
//token秘鑰 private static final String TOKEN_SECRET = "ZCfasfhuaUUHufguGuwu2020BQWE";
關(guān)于上面的問題,給出一個簡單易懂的方案~
jwt 來生成token,還有一個玩法,用戶登錄時,生成token的 SecretKey 是一個隨機數(shù),也就是說每個用戶,每次登錄時jwt SecretKey 是隨機數(shù),并保存到緩存,key是登錄賬戶,(當(dāng)然了,分布式緩存的話,就用Redis,sqlserver緩存等等),總之,客戶端訪問接口是,header 要帶登錄賬戶,和token,服務(wù)端拿到登錄賬號,到緩存去撈相應(yīng)的SecretKey ,然后再進行token校驗??梢苑纻卧靦oken了(這個方案在一定程度上能防止偽造,但是不能防止token泄露被劫持)。
到此,關(guān)于“Token登陸驗證機制怎么實現(xiàn)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。