
步驟分析:
1.首先我們用戶會找到我們的網(wǎng)站
8081是網(wǎng)關端口,/api/是網(wǎng)關放行的路徑
- 比如地址是:http:localhost:8001/api/oauth/toLogin,用戶點擊后直接會訪問網(wǎng)關,我們會在網(wǎng)關的AuthFilter過濾器中判斷用戶是否是登錄請求,如果是登錄,和相關必須要放行的請求,我們就可以直接放行,讓它去訪問登錄等相關資源.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.login頁面
用戶看到登錄的頁面就可以輸入賬號密碼進行登錄,當用戶點擊登錄就會發(fā)送一個請求http:localhost:8001/api/oauth/login登錄請求,網(wǎng)關放行(UrlFilter包含了需要放行的請求)
if ("/api/oauth/login".equals(path) || !UrlFilter.hasAuthorize(path) ){
// if ("/api/oauth/login".equals(path) ){
//直接放行
return chain.filter(exchange);
}
3.生成令牌(用戶認證,也解決單點登錄問題)
將用戶輸入的用戶名和密碼發(fā)送到login的controller中,這時如果輸入為空直接 返回錯誤信息然后去調(diào)用申請令牌的service的方法,傳入用戶名,密碼和客戶端id和客戶端密碼,這時在申請令牌的時候,認證服務會自動校驗客戶端id和客戶端密碼,自動查詢oauth_client_details表,我們會在認證工具類中用過feign的遠程調(diào)用user服務,用過用戶名去查詢出user對象,然后認證框架自動幫我們校驗,生成最終的jwt令牌,它包含了6部分數(shù)據(jù):
//申請令牌
AuthToken token = authService.login(username, password, clientId, clientSecret);

access_token:訪問令牌,攜帶此令牌訪問資源
token_type:有MAC Token與Bearer Token兩種類型,兩種的校驗算法不同,Oauth2采 用 Bearer Token。
refresh_token:刷新令牌,使用此令牌可以延長訪問令牌的過期時間。
expires_in:過期時間,單位為秒。
scope:范圍,與定義的客戶端范圍一致。
jti:當前token的唯一標識
拿到令牌后我們會在方法中取出jwt令牌的值,存儲到redis中,設置它的過期時間
//3.將jwt作為redis中的key, 將jwt作為redis中的value進行數(shù)據(jù)的存儲
/*
參數(shù) authToken設置 redis key
set 對應的值
ttl 過期時間
TimeUnit :時間單位 SECONDS:秒
* */
stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);
然后返回令牌,在controller層拿到令牌后 取出jti短令牌存儲到cookie中
CookieUtil.addCookie(response,cookieDomain,"/","uid",jti,cookieMaxAge,false);
到這里,用戶就登錄成功了提示用戶,也可以跳轉相關頁面.
4.訪問受保護的資源
這時用戶就能夠訪問我們受保護的資源了,用戶會發(fā)起請求路徑到相關服務層,會經(jīng)過網(wǎng)關過濾器,不是登錄請求不放行,然后校驗cookie中有沒有短令牌,如果有判斷redis中有沒有存儲jwt令牌信息(存在過期),不滿足條件返回401權限不足: return response.setComplete();
都滿足條件,對這次用戶請求頭進行增強操作:
//4.對當前的請求對象進行增強,讓它會攜帶令牌的信息
request.mutate().header("Authorization","Bearer "+jwt);
return chain.filter(exchange);
用戶請求到達服務層后,認證服務會自動對jwt令牌進行校驗解析,解析通過后訪問被保護的資源,
解析不通過返回權限不足錯誤.