Spring Security 整合 JSON Web Token(JWT)

注:參考Spring Security 整合 JSON Web Token(JWT) 提升 REST 安全性火本,寫的特別全面伺糠,本文只是學(xué)習(xí)總結(jié)

JWT:

基于token的鑒權(quán)機(jī)制

基于token的鑒權(quán)機(jī)制類似于http協(xié)議也是無狀態(tài)的,它不需要在服務(wù)端去保留用戶的認(rèn)證信息或者會話信息明场。這就意味著基于token認(rèn)證機(jī)制的應(yīng)用不需要去考慮用戶在哪一臺服務(wù)器登錄了否过,這就為應(yīng)用的擴(kuò)展提供了便利午笛。

流程上是這樣的:

1.用戶使用用戶名密碼來請求服務(wù)器

2.服務(wù)器進(jìn)行驗(yàn)證用戶的信息

3.服務(wù)器通過驗(yàn)證發(fā)送給用戶一個(gè)token

4.客戶端存儲token,并在每次請求時(shí)附送上這個(gè)token值

5.服務(wù)端驗(yàn)證token值苗桂,并返回?cái)?shù)據(jù)

這個(gè)token必須要在每次請求時(shí)傳遞給服務(wù)端药磺,它應(yīng)該保存在請求頭里, 另外煤伟,服務(wù)端要支持CORS(跨來源資源共享)策略癌佩,一般我們在服務(wù)端這么做就可以了Access-Control-Allow-Origin: *。

JWT的構(gòu)成

第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload, 類似于飛機(jī)上承載的物品)便锨,第三部分是簽證(signature).

header

jwt的頭部承載兩部分信息:

聲明類型围辙,這里是jwt

聲明加密的算法 通常直接使用 HMAC SHA256

完整的頭部就像下面這樣的JSON:

{

'typ':'JWT',

'alg':'HS256'

}

然后將頭部進(jìn)行base64加密(該加密是可以對稱解密的),構(gòu)成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

playload

載荷就是存放有效信息的地方。這個(gè)名字像是特指飛機(jī)上承載的貨品放案,這些有效信息包含三個(gè)部分

1.標(biāo)準(zhǔn)中注冊的聲明

2.公共的聲明

3.私有的聲明

標(biāo)準(zhǔn)中注冊的聲明(建議但不強(qiáng)制使用) :

iss: jwt簽發(fā)者

sub: jwt所面向的用戶

aud: 接收jwt的一方

exp: jwt的過期時(shí)間姚建,這個(gè)過期時(shí)間必須要大于簽發(fā)時(shí)間

nbf: 定義在什么時(shí)間之前,該jwt都是不可用的.

iat: jwt的簽發(fā)時(shí)間

jti: jwt的唯一身份標(biāo)識吱殉,主要用來作為一次性token,從而回避重放攻擊掸冤。

公共的聲明

公共的聲明可以添加任何的信息厘托,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息.但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷?

私有的聲明

私有聲明是提供者和消費(fèi)者所共同定義的聲明贩虾,一般不建議存放敏感信息催烘,因?yàn)閎ase64是對稱解密的沥阱,意味著該部分信息可以歸類為明文信息缎罢。

定義一個(gè)payload:

{"sub":"1234567890","name":"John Doe","admin":true}

然后將其進(jìn)行base64加密,得到Jwt的第二部分考杉。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

signature

jwt的第三部分是一個(gè)簽證信息策精,這個(gè)簽證信息由三部分組成:

1.header (base64后的)

2.payload (base64后的)

3.secret

這個(gè)部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,然后通過header中聲明的加密方式進(jìn)行加鹽secret組合加密崇棠,然后就構(gòu)成了jwt的第三部分咽袜。

// javascript

var ?encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString,'secret');

// TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

將這三部分用.連接成一個(gè)完整的字符串,構(gòu)成了最終的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服務(wù)器端的,jwt的簽發(fā)生成也是在服務(wù)器端的枕稀,secret就是用來進(jìn)行jwt的簽發(fā)和jwt的驗(yàn)證询刹,所以,它就是你服務(wù)端的私鑰萎坷,在任何場景都不應(yīng)該流露出去凹联。一旦客戶端得知這個(gè)secret, 那就意味著客戶端是可以自我簽發(fā)jwt了。

如何應(yīng)用

一般是在請求頭里加入Authorization哆档,并加上Bearer標(biāo)注:

fetch('api/user/1',{

? ? ? ? ? headers:{

? ? ? ? ? ? ? ? ? ? 'Authorization':'Bearer '+ token?

? ? ? ? ? ? ? ? ? ? ? }

})

服務(wù)端會驗(yàn)證token蔽挠,如果驗(yàn)證通過就會返回相應(yīng)的資源。整個(gè)流程就是這樣的:

jwt-diagram

總結(jié)

優(yōu)點(diǎn)

因?yàn)閖son的通用性瓜浸,所以JWT是可以進(jìn)行跨語言支持的澳淑,像JAVA,JavaScript,NodeJS,PHP等很多語言都可以使用。

因?yàn)橛辛藀ayload部分插佛,所以JWT可以在自身存儲一些其他業(yè)務(wù)邏輯所必要的非敏感信息杠巡。

便于傳輸,jwt的構(gòu)成非常簡單雇寇,字節(jié)占用很小氢拥,所以它是非常便于傳輸?shù)摹?/p>

它不需要在服務(wù)端保存會話信息, 所以它易于應(yīng)用的擴(kuò)展

安全相關(guān)

不應(yīng)該在jwt的payload部分存放敏感信息,因?yàn)樵摬糠质强蛻舳丝山饷艿牟糠帧?/p>

保護(hù)好secret私鑰谢床,該私鑰非常重要兄一。

如果可以,請使用https協(xié)議

在SpringBoot中整合JWTSpring Security的步奏:

1.在項(xiàng)目中引入(本項(xiàng)目使用Gradle)

compile group:'org.springframework.boot',name:'spring-boot-starter-mobile',version:'1.5.4.RELEASE'

compile group:'org.springframework.boot',name:'spring-boot-starter-security',version:'1.5.4.RELEASE'

compile group:'io.jsonwebtoken',name:'jjwt',version:'0.7.0'

2.配置

目錄結(jié)構(gòu)如下:

WebSecurityConfig文件:

@SuppressWarnings("SpringJavaAutowiringInspection")

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled=true)

public ?class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

privateJwtAuthenticationEntryPointunauthorizedHandler;

@Autowired

?private UserDetailsService userDetailsService;

@Autowired

public void configureAuthentication(AuthenticationManagerBuilder ?authenticationManagerBuilder) throws Exception {

? authenticationManagerBuilder

? ? ? ? ?.userDetailsService(this.userDetailsService)

? ? ? ? ?.passwordEncoder(passwordEncoder());

? ? ?}

@Bean

public PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

? ? }

@Bean

public ?JwtAuthenticationTokenFilter authenticationTokenFilterBean()throwsException {

? ? ? ?return newJwtAuthenticationTokenFilter();

? ? ?}

@Override

protected voidconfigure(HttpSecurity httpSecurity)throwsException {

httpSecurity

// we don't need CSRF because our token is invulnerable

.csrf().disable()

.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()

// don't create session

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

.authorizeRequests()

//.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

// allow anonymous resource requests

.antMatchers(

HttpMethod.GET,

"/",

"/*.html",

"/favicon.ico",

"/**/*.html",

"/**/*.css",

"/**/*.js"

).permitAll()

.antMatchers("/auth/**").permitAll()

.anyRequest().authenticated();

// Custom JWT based security filter

httpSecurity

?.addFilterBefore(authenticationTokenFilterBean(),UsernamePasswordAuthenticationFilter.class); ?

? // disable page caching

? httpSecurity.headers().cacheControl();

? ? ? }

作者:誰在烽煙彼岸

鏈接:http://www.reibang.com/p/beea4bc9056b

來源:簡書

著作權(quán)歸作者所有识腿。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)出革,非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渡讼,一起剝皮案震驚了整個(gè)濱河市骂束,隨后出現(xiàn)的幾起案子耳璧,更是在濱河造成了極大的恐慌,老刑警劉巖展箱,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旨枯,死亡現(xiàn)場離奇詭異,居然都是意外死亡混驰,警方通過查閱死者的電腦和手機(jī)攀隔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栖榨,“玉大人昆汹,你說我怎么就攤上這事∮ぴ裕” “怎么了满粗?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長愚争。 經(jīng)常有香客問我映皆,道長,這世上最難降的妖魔是什么轰枝? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任捅彻,我火速辦了婚禮,結(jié)果婚禮上狸膏,老公的妹妹穿的比我還像新娘沟饥。我一直安慰自己,他們只是感情好湾戳,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布贤旷。 她就那樣靜靜地躺著,像睡著了一般砾脑。 火紅的嫁衣襯著肌膚如雪幼驶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天韧衣,我揣著相機(jī)與錄音盅藻,去河邊找鬼。 笑死畅铭,一個(gè)胖子當(dāng)著我的面吹牛氏淑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播硕噩,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼假残,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辉懒,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤阳惹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后眶俩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莹汤,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年颠印,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纲岭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗽仪,死狀恐怖荒勇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闻坚,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布兢孝,位于F島的核電站窿凤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跨蟹。R本人自食惡果不足惜雳殊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窗轩。 院中可真熱鬧夯秃,春花似錦、人聲如沸痢艺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堤舒。三九已至色建,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舌缤,已是汗流浹背箕戳。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留国撵,地道東北人陵吸。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像介牙,于是被迫代替她去往敵國和親壮虫。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容

  • The crazy thing: the subways here in Seoul are also doubl...
    潤琦閱讀 96評論 0 0
  • 姓名:施千惠 時(shí)間:1小時(shí)30分 書名:《佐賀的超級阿嬤》 讀書心得: 這本書講的是耻瑟,在廣島原子彈爆...
    施千惠閱讀 266評論 0 0
  • 今天第一天上學(xué)我很開心旨指,學(xué)校的午飯很好吃赏酥、同學(xué)們都很好、我很喜歡我的班主任安老師谆构、她還給我們發(fā)小貼畫裸扶、還有戴老師、...
    劉美彤閱讀 280評論 0 2