认证令牌_Java应用程序的令牌认证
認(rèn)證令牌
建筑物身份管理,包括身份驗證和授權(quán)? 嘗試Stormpath! 我們的REST API和強大的Java SDK支持可以消除您的安全風(fēng)險,并且可以在幾分鐘內(nèi)實現(xiàn)。 注冊 ,再也不會建立auth了!
2016年5月12日更新:構(gòu)建Java應(yīng)用程序? JJWT是由我們自己的Les Hazlewood開發(fā)的Java庫,提供端到端JWT的創(chuàng)建和驗證。 JJWT永久免費且開源(Apache許可證,版本2.0),易于使用和理解。 它的設(shè)計采用了以構(gòu)建者為中心的流暢界面,從而掩蓋了其大部分復(fù)雜性。 我們希望您能嘗試一下 ,并告訴我們您的想法! (而且,如果您是Node開發(fā)人員,請查看NJWT !)
在我的上一篇文章中 ,我們涵蓋了很多基礎(chǔ),包括我們傳統(tǒng)上如何保護網(wǎng)站安全,使用cookie和會話的一些陷阱以及如何通過傳統(tǒng)方式解決這些陷阱。
在本文中,我們將超越傳統(tǒng),深入探討如何使用JWT(JSON Web令牌)進行令牌身份驗證,不僅解決了這些問題,而且還使我們受益于可檢查的元數(shù)據(jù)和強大的加密簽名。
救援的令牌認(rèn)證!
首先讓我們檢查一下在這種情況下authentication和token含義。
身份驗證證明用戶就是他們所說的真實身份。
令牌是一個獨立的信息塊。 它可能具有內(nèi)在價值,也可能沒有。 我們將研究一種特定類型的令牌, 它確實具有內(nèi)在價值,并通過會話ID解決了許多問題。
JSON Web令牌(JWT)
JWT是URL安全,緊湊,自包含的字符串,其中包含有意義的信息,這些信息通常經(jīng)過數(shù)字簽名或加密。 它們正Swift成為網(wǎng)絡(luò)上令牌實施的實際標(biāo)準(zhǔn)。
URL安全是一種說法,它表示整個字符串都已編碼,因此沒有特殊字符,并且令牌可以放入URL中。
該字符串是不透明的,可以與使用會話ID幾乎相同的方式獨立使用。 不透明是指查看字符串本身沒有提供任何其他信息。
但是,還可以對字符串進行解碼以提取元數(shù)據(jù),并且可以對簽名進行加密驗證,以使您的應(yīng)用程序知道令牌未被篡改。
JWT和OAuth2訪問令牌
許多OAuth2實現(xiàn)都將JWT用于其訪問令牌。 應(yīng)該指出,OAuth2和JWT規(guī)范是彼此完全獨立的,彼此之間沒有任何依賴關(guān)系。 將JWT用作OAuth2的令牌機制會帶來很多好處,我們將在下面看到。
JWT可以存儲在cookie中,但是我們之前討論的cookie的所有規(guī)則仍然適用。 您可以將會話ID完全替換為JWT。 然后,您可以獲得直接從該會話ID訪問元信息的其他好處。
在野外,它們看起來就像是另一個丑陋的弦:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9.43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs如果仔細(xì)看,您會看到字符串中有兩個句點。 這些意義重大,因為它們界定了JWT的不同部分。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 . eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9 . 43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLsJWT結(jié)構(gòu)
JWT具有三部分結(jié)構(gòu),每個部分都是base64編碼的:
以下是解碼的部分:
標(biāo)頭
{"typ": "JWT","alg": "HS256" }索償
{"iss":"http://trustyapp.com/","exp": 1300819380,"sub": "users/8983462","scope": "self api/buy" }密碼簽名
t?′—?à%O?v+n?…SZuˉμ€U…8H×智威湯遜索賠
讓我們檢查索賠部分。 可以在此處找到屬于JWT規(guī)范的每種聲明。
iss是發(fā)行令牌的人。
exp是令牌過期的時間。
sub是令牌的主題。 這通常是某種用戶標(biāo)識符。
權(quán)利要求的以上部分全部包含在JWT規(guī)范中。 scope未包含在規(guī)范中,但通常用于提供授權(quán)信息。 也就是說,用戶可以訪問應(yīng)用程序的哪些部分。
JWT的一個優(yōu)點是,可以將任意數(shù)據(jù)編碼到上述scope的權(quán)利要求中。 另一個優(yōu)點是,客戶端現(xiàn)在可以對該信息做出React,而無需與服務(wù)器進行任何進一步的交互。 例如,可以基于在scope權(quán)利要求中找到的數(shù)據(jù)來隱藏頁面的一部分。
注意 :服務(wù)器始終驗證客戶機采取的操作仍然很關(guān)鍵,也是最佳實踐。 例如,如果正在對客戶端執(zhí)行某些管理操作,則您仍將需要在應(yīng)用程序服務(wù)器上驗證當(dāng)前用戶是否有權(quán)執(zhí)行該操作。 您永遠(yuǎn)不會僅依賴客戶端授權(quán)信息。
您可能已經(jīng)獲得了另一個好處:加密簽名。 簽名可以被驗證,證明JWT未被篡改。 請注意,密碼簽名的存在不能保證機密性。 僅當(dāng)對JWT進行加密和簽名時,才能確保機密性。
現(xiàn)在,最重要的是: 無國籍 。 盡管服務(wù)器將需要生成JWT,但由于所有用戶元數(shù)據(jù)都已直接編碼到JWT中,因此它不需要將其存儲在任何地方。 服務(wù)器和客戶端可以來回傳遞JWT,而從不存儲它。 這樣可以很好地擴展。
管理承載令牌安全性
隱式信任是一種折衷。 這些類型的令牌通常被稱為承載令牌,因為獲得對應(yīng)用程序受保護部分的訪問所需的全部就是有效的未過期令牌的表示。
您必須解決以下問題:令牌應(yīng)使用多長時間? 您將如何撤銷它? (還有其他整篇文章可以針對刷新令牌進行 。)
如果未加密,則必須注意存儲在JWT中的內(nèi)容。 不要存儲任何敏感信息。 以sub權(quán)利要求的形式存儲用戶標(biāo)識符是公認(rèn)的慣例。 當(dāng)JWT簽名時,它稱為JWS。 加密后,稱為JWE。
Java,JWT和您!
我們?yōu)镚ithub上的JJWT項目感到自豪。 它是由Stormpath的首席技術(shù)官Les Hazlewood最初撰寫的,它是針對Java的完全開源的JWT解決方案。 它是最易于使用和理解的庫,用于在JVM上創(chuàng)建和驗證JSON Web令牌。
您如何創(chuàng)建JWT? 十分簡單!
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm;byte[] key = getSignatureKey();String jwt = Jwts.builder().setIssuer("http://trustyapp.com/").setSubject("users/1300819380").setExpiration(expirationDate).put("scope", "self api/buy") .signWith(SignatureAlgorithm.HS256,key).compact();首先要注意的是用于創(chuàng)建JWT的流暢的 Builder API。 方法調(diào)用被鏈接在一起,最終以compact調(diào)用返回最終的JWT字符串。
還要注意,當(dāng)我們設(shè)置規(guī)范中的一項權(quán)利要求時,我們使用了二傳手。 例如: .setSubject("users/1300819380") 。 設(shè)置自定義聲明后,我們會使用調(diào)用來放置并指定鍵和值。 例如: .put("scope", "self api/buy")
驗證JWT一樣容易。
String subject = "HACKER"; try {Jws jwtClaims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt);subject = claims.getBody().getSubject();//OK, we can trust this JWT} catch (SignatureException e) {//don't trust the JWT! }如果對JWT進行了任何篡改,則解析聲明將引發(fā)SignatureException并且subject變量的值將保持HACKER 。 如果它是有效的JWT,則將從中提取subject : claims.getBody().getSubject()
什么是OAuth?
在下一部分中,我們將看一個使用Stormpath的OAuth2實現(xiàn)的示例,該實現(xiàn)利用了JWT。
OAuth2規(guī)范周圍有很多困惑。 那部分是因為它確實是über規(guī)范–它具有很多復(fù)雜性。 這也是因為OAuth1.a和OAuth2是非常不同的野獸。 我們將看一看OAuth2規(guī)范的一個非常具體,易于使用的子集。 我們有一篇很棒的文章,它詳細(xì)介紹了什么是OAuth 。 在這里,我們將提供一些簡短的背景知識,然后直接進入示例。
OAuth2基本上是一種支持授權(quán)工作流程的協(xié)議。 這意味著它為您提供了一種確保特定用戶有權(quán)執(zhí)行某項操作的方法。
而已。
OAuth2 并不旨在執(zhí)行諸如驗證用戶身份之類的工作, 而是由身份驗證服務(wù)負(fù)責(zé)。 身份驗證是在驗證用戶身份( 例如要求輸入用戶名/密碼 )時進行的驗證,而授權(quán)是在檢查現(xiàn)有用戶已擁有的權(quán)限時進行的驗證。
請記住,OAuth2是授權(quán)協(xié)議。
使用OAuth授權(quán)類型進行授權(quán)
讓我們看一下典型的OAuth2交互。
POST /oauth/token HTTP/1.1 Origin: https://foo.com Content-Type: application/x-www-form-urlencodedgrant_type=password&username=username&password=passwordgrant_type是grant_type 。 這種交互類型也需要application/x-www-form-urlencoded內(nèi)容類型。 假設(shè)您通過網(wǎng)絡(luò)傳遞用戶名和密碼,則始終希望連接是安全的。 不過,好處是響應(yīng)將具有OAuth2承載令牌。 然后,此令牌將用于以后瀏覽器與服務(wù)器之間的每次交互。 這里有一個非常簡短的介紹,其中用戶名和密碼是通過網(wǎng)絡(luò)傳遞的。 假設(shè)服務(wù)器上的身份驗證服務(wù)驗證了用戶名和密碼,則響應(yīng)如下:
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA...","token_type":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA...","example_parameter":"example_value" }注意Cache-Control和Pragma標(biāo)頭。 我們不希望此響應(yīng)被緩存在任何地方。 access_token是瀏覽器在后續(xù)請求中將使用的內(nèi)容。 同樣,OAuth2和JWT之間沒有直接關(guān)系。 但是, access_token可以是JWT。 這就是編碼的元數(shù)據(jù)的額外好處所在。這是在以后的請求中利用訪問令牌的方式:
GET /admin HTTP/1.1 Authorization: Bearer 2YotnFZFEjr1zCsicMW...Authorization標(biāo)頭是標(biāo)準(zhǔn)標(biāo)頭。 使用OAuth2不需要自定義標(biāo)頭。 在這種情況下,類型是Bearer而不是Basic類型。 訪問令牌直接包含在Bearer關(guān)鍵字之后。 這樣就完成了密碼授予類型的O??Auth2交互。 瀏覽器的每個后續(xù)請求都可以將Authorizaion: Bearer標(biāo)頭與訪問令牌一起使用。
還有一種稱為client_credentials授予類型,它使用client_id和client_secret而不是username和password 。 此授予類型通常用于API交互。 盡管客戶端ID和秘密密鑰的功能類似于用戶名和密碼,但它們通常具有更高的安全性,并且不一定是人類可讀的。
帶我們回家:OAuth2 Java示例
我們到了! 現(xiàn)在該深入研究一些演示JWT的特定代碼了。
Spring Boot Web MVC
Stormpath Java SDK中有許多示例。 在這里,我們將看一個Spring Boot Web MVC示例。 這是示例中的HelloController :
@RestController public class HelloController {@RequestMapping("/")String home(HttpServletRequest request) {String name = "World";Account account = AccountResolver.INSTANCE.getAccount(request);if (account != null) {name = account.getGivenName();}return "Hello " + name + "!";}}對于此演示而言,關(guān)鍵是:
Account account = AccountResolver.INSTANCE.getAccount(request);
在幕后,僅當(dāng)存在經(jīng)過身份驗證的會話時, account才會解析為Account對象(而不是null )。
生成并運行示例代碼
要構(gòu)建并運行此示例,請執(zhí)行以下操作:
? dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java (master|8100m) ? cd examples/spring-boot-webmvc/ ? dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8100m) ? mvn clean package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Stormpath Java SDK :: Examples :: Spring Boot Webapp 1.0.RC4.6-SNAPSHOT [INFO] ------------------------------------------------------------------------... skipped output ...[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.865 s [INFO] Finished at: 2015-08-04T11:46:05-04:00 [INFO] Final Memory: 31M/224M [INFO] ------------------------------------------------------------------------ ? dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8100m啟動Spring Boot示例
然后,您可以像這樣啟動Spring Boot示例:
? dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8104m) ? java -jar target/stormpath-sdk-examples-spring-boot-web-1.0.RC4.6-SNAPSHOT.jar. ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot :: (v1.2.1.RELEASE)2015-08-04 11:51:00.127 INFO 17973 --- [ main] tutorial.Application : Starting Application v1.0.RC4.6-SNAPSHOT on MacBook-Pro.local with PID 17973 ... skipped output ...2015-08-04 11:51:04.558 INFO 17973 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2015-08-04 11:51:04.559 INFO 17973 --- [ main] tutorial.Application : Started Application in 4.599 seconds (JVM running for 5.103)注意 :假設(shè)您已經(jīng)設(shè)置了一個Stormpath帳戶,并且您的api密鑰位于~/.stormpath/apiKey.properties 。 在此處查找有關(guān)使用Spring Boot快速設(shè)置Stormpath的更多信息。
使用JSON Web令牌進行身份驗證(或不進行身份驗證)
現(xiàn)在,我們可以練習(xí)該示例,并展示一些實際應(yīng)用中的JWT! 首先,無需任何身份驗證即可命中端點。 我喜歡使用httpie ,但是任何命令行http客戶端都可以。
? http -v localhost:8080 GET / HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Connection: keep-alive Host: localhost:8080 User-Agent: HTTPie/0.9.2HTTP/1.1 200 OK Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, ... Content-Length: 12 Content-Type: text/plain;charset=UTF-8 Date: Tue, 04 Aug 2015 15:56:41 GMT Server: Apache-Coyote/1.1Hello World!-v參數(shù)產(chǎn)生詳細(xì)的輸出,并顯示請求和響應(yīng)的所有標(biāo)頭。 在這種情況下,輸出消息就是: Hello World! 。 這是因為沒有建立的會話。
使用Stormpath OAuth端點進行身份驗證
現(xiàn)在,讓我們點擊oauth端點,以便我們的服務(wù)器可以使用Stormpath進行身份驗證。 您可能會問,“什么是oauth端點?” 上面的控制器未指示任何此類端點。 示例中是否還有其他具有其他端點的控制器? 不是,沒有! Stormpath提供了開箱即用的oauth(和許多其他)端點。 看看這個:
? http -v --form POST http://localhost:8080/oauth/token \ > 'Origin:http://localhost:8080' \ > grant_type=password username=micah+demo.jsmith@stormpath.com password= POST /oauth/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: localhost:8080 Origin: http://localhost:8080 User-Agent: HTTPie/0.9.2grant_type=password&username=micah%2Bdemo.jsmith%40stormpath.com&password=HTTP/1.1 200 OK Cache-Control: no-store Content-Length: 325 Content-Type: application/json;charset=UTF-8 Date: Tue, 04 Aug 2015 16:02:08 GMT Pragma: no-cache Server: Apache-Coyote/1.1 Set-Cookie: account=eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4; Expires=Wed, 05-Aug-2015 16:02:08 GMT; Path=/; HttpOnly{"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4","expires_in": 259200,"token_type": "Bearer" }這里有很多事情,所以讓我們分解一下。
在第一行中,我告訴httpie我想創(chuàng)建一個表單url編碼的--form這就是--form和POST參數(shù)的作用。 我正在命中本地運行的服務(wù)器的/oauth/token端點。 我指定一個Origin標(biāo)頭。 出于我們先前提到的安全原因,與Stormpath進行交互是必需的。 按照OAuth2規(guī)范,我要傳遞grant_type=password以及username和password 。
響應(yīng)具有Set-Cookie標(biāo)頭以及包含OAuth2訪問令牌的JSON正文。 你猜怎么著? 該訪問令牌也是JWT。 以下是已解碼的聲明:
{"jti": "14426d13-f58b-4a41-bede-0b343fcd1ac0","iat": 1438704128,"sub": "https://api.stormpath.com/v1/accounts/5oM4WI3P4xIwp4WiDbRj80","exp": 1438963328 }注意sub鍵。 這就是我驗證為的帳戶的完整Stormpath URL。 現(xiàn)在,讓我們再次點擊基本的Hello World端點,僅這次,我們將使用OAuth2訪問令牌:
? http -v localhost:8080 \ > 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4' GET / HTTP/1.1 Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4 Connection: keep-alive Host: localhost:8080 User-Agent: HTTPie/0.9.2HTTP/1.1 200 OK Content-Length: 11 Content-Type: text/plain;charset=UTF-8 Date: Tue, 04 Aug 2015 16:44:28 GMT Server: Apache-Coyote/1.1Hello John!請注意,在輸出的最后一行中,消息是通過名稱尋址我們的。 現(xiàn)在,我們已經(jīng)使用OAuth2與Stormpath建立了經(jīng)過身份驗證的會話,控制器中的這些行將檢索名字:
Account account = AccountResolver.INSTANCE.getAccount(request); if (account != null) {name = account.getGivenName(); }摘要:Java應(yīng)用程序的令牌認(rèn)證
在本文中,我們研究了如何使用JWT進行令牌身份驗證,不僅解決了傳統(tǒng)方法的問題,而且還為我們提供了可檢查的元數(shù)據(jù)和強大的密碼簽名的好處。
我們概述了OAuth2協(xié)議,并詳細(xì)介紹了Stormpath的OAuth2實現(xiàn)如何使用JWT。
以下是指向基于令牌的身份驗證,JWT和Spring Boot的帖子的其他鏈接:
- Angular.js的基于令牌的身份驗證
- JJWT –適用于Java和Android的JSON Web令牌
- Spring Boot Webapp示例快速入門
- JWT規(guī)范
建筑物身份管理,包括身份驗證和授權(quán)? 嘗試Stormpath! 我們的REST API和強大的Java SDK支持可以消除您的安全風(fēng)險,并且可以在幾分鐘內(nèi)實現(xiàn)。 注冊 ,再也不會建立auth了!
翻譯自: https://www.javacodegeeks.com/2016/07/token-authentication-java-applications.html
認(rèn)證令牌
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的认证令牌_Java应用程序的令牌认证的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 住建备案证号怎么查询(住建备案证号)
- 下一篇: 可靠的ddos防护厂家(可靠的ddos防