認(rèn)證開發(fā)+Oauth2(授權(quán)碼)模式+Spring Security+網(wǎng)關(guān)解說

單點(diǎn).png

步驟分析:

1.首先我們用戶會找到我們的網(wǎng)站

8081是網(wǎng)關(guān)端口,/api/是網(wǎng)關(guān)放行的路徑

  • 比如地址是:http:localhost:8001/api/oauth/toLogin,這時會給他顯示第三方登錄暴露的接口圖標(biāo),比如(qq,微信,微博)
1.1 用戶點(diǎn)擊微信登錄
  • 微信會展示一個二維碼讓用戶進(jìn)行掃碼認(rèn)證,掃碼后微信會提示用戶是否授權(quán)(意思是暴露用戶的信息),用戶點(diǎn)擊確定后,微信會提供一個授權(quán)碼給給我們的網(wǎng)站\color{red}{(會頒發(fā)一個appid客戶端id 和客戶端密碼和唯一標(biāo)識給我們網(wǎng)站)}
    我們的網(wǎng)站會拿到code授權(quán)碼,我們會攜帶授權(quán)碼去找微信接口申請令牌,,然后微信會頒發(fā)給我們一個token令牌,我們會拿到這個令牌訪問微信接口,接口會自動解析令牌,返回用戶的信息(用戶名和頭像)給我們網(wǎng)站,根據(jù)用戶信息關(guān)聯(lián)查詢我們自己的用戶數(shù)據(jù).我們這時第三方登錄就已經(jīng)完成了.
  • 根據(jù)我們的業(yè)務(wù)需求,可以選擇拿到信息后直接在后端過濾器放行,生成令牌,存cookie和redis中,用戶信息存入數(shù)據(jù)庫.
1.2 業(yè)務(wù)需求(再次網(wǎng)站登錄)
  • 也可以讓用戶進(jìn)行我們網(wǎng)站的登錄,輸入用戶名和密碼進(jìn)行認(rèn)證,用戶點(diǎn)擊后直接會訪問網(wǎng)關(guān),我們會在網(wǎng)關(guān)的AuthFilter過濾器中判斷用戶是否是登錄請求,如果是登錄,和相關(guān)必須要放行的請求,我們就可以直接放行,讓它去訪問登錄等相關(guān)資源.
    \color{red}{注意必須要添加這個依賴,不然不會跳轉(zhuǎn)頁面而是直接重定向}
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
2.login頁面

用戶看到登錄的頁面就可以輸入賬號密碼進(jìn)行登錄娃善,當(dāng)用戶點(diǎn)擊登錄就會發(fā)送一個請求http:localhost:8001/api/oauth/login登錄請求,網(wǎng)關(guān)放行(UrlFilter包含了需要放行的請求)

if ("/api/oauth/login".equals(path) || !UrlFilter.hasAuthorize(path) ){
     //   if ("/api/oauth/login".equals(path) ){
            //直接放行
            return chain.filter(exchange);
        }
3.生成令牌(Spring Security框架自動校驗(yàn)用戶名密碼,也解決單點(diǎn)登錄問題)

將用戶輸入的用戶名和密碼發(fā)送到login的controller中,這時如果輸入為空直接 返回錯誤信息
然后去調(diào)用申請令牌的service中的exchange方法傳入客戶端id和客戶端密碼和用戶輸入的用戶名和密碼.在申請令牌的時候,通過用戶傳來的用戶名去工具類中用過feign的遠(yuǎn)程調(diào)用user服務(wù),查詢用戶信息客,通過Spring Security框架去校驗(yàn)用戶傳來的密碼和查詢出來的密碼比對,通過客戶端id和客戶端密碼,自動查詢oauth_client_details表,通過后,生成最終的jwt令牌,它包含了6部分?jǐn)?shù)據(jù):

//申請令牌
        AuthToken token = authService.login(username, password, clientId, clientSecret);
     /*       *  url ,請求路徑 http://localhost:9200/oauth/token
         *  HttpMethod ;請求方式
         *  requestEntity :封裝請求的數(shù)據(jù)
         * Map :數(shù)據(jù)的返回方式  */
        //這里的參數(shù)是注冊到Eureka上的服務(wù)名稱
        ServiceInstance choose = loadBalancerClient.choose("user-auth");
        URI uri = choose.getUri();
        String url = uri+"/oauth/token";
restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class); //反回申請的令牌

單點(diǎn).png

access_token:訪問令牌论衍,攜帶此令牌訪問資源
token_type:有MAC Token與Bearer Token兩種類型,兩種的校驗(yàn)算法不同聚磺,Oauth2采 用 Bearer Token坯台。
refresh_token:刷新令牌,使用此令牌可以延長訪問令牌的過期時間瘫寝。
expires_in:過期時間蜒蕾,單位為秒稠炬。
scope:范圍,與定義的客戶端范圍一致咪啡。
jti:當(dāng)前token的唯一標(biāo)識

拿到令牌后我們會在方法中取出jwt令牌的值,存儲到redis中,設(shè)置它的過期時間

//3.將jwt作為redis中的key, 將jwt作為redis中的value進(jìn)行數(shù)據(jù)的存儲
        /*
        參數(shù)  authToken設(shè)置 redis key 
             set 對應(yīng)的值
              ttl 過期時間
              TimeUnit :時間單位  SECONDS:秒
        * */
stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);

然后返回令牌,在controller層拿到令牌后 取出jti短令牌存儲到cookie中

 CookieUtil.addCookie(response,cookieDomain,"/","uid",jti,cookieMaxAge,false);

到這里,用戶就登錄成功了提示用戶,也可以跳轉(zhuǎn)相關(guān)頁面.

4.訪問受保護(hù)的資源

這時用戶就能夠訪問我們受保護(hù)的資源了,用戶會發(fā)起請求路徑到相關(guān)服務(wù)層,會經(jīng)過網(wǎng)關(guān)過濾器,不是登錄請求不放行,然后校驗(yàn)cookie中有沒有短令牌,如果有判斷redis中有沒有存儲jwt令牌信息(存在過期),不滿足條件返回401權(quán)限不足: return response.setComplete();
都滿足條件,對這次用戶請求頭進(jìn)行增強(qiáng)操作:

  //4.對當(dāng)前的請求對象進(jìn)行增強(qiáng),讓它會攜帶令牌的信息
        request.mutate().header("Authorization","Bearer "+jwt);
        return chain.filter(exchange);

用戶請求到達(dá)服務(wù)層后,認(rèn)證服務(wù)會自動對jwt令牌進(jìn)行校驗(yàn)解析,解析通過后訪問被保護(hù)的資源,
解析不通過返回權(quán)限不足錯誤.解析通過我們還會在每一個服務(wù)的方法上加@PreAuthorize權(quán)限注解,判斷是否滿足權(quán)限條件,不滿足則跳轉(zhuǎn)到登錄頁面

//跳轉(zhuǎn)登錄頁面
    private Mono<Void> toLoginPage(String loginUrl, ServerWebExchange exchange) {

        ServerHttpResponse response = exchange.getResponse();

        //設(shè)置狀態(tài)碼  //302 重定向
        response.setStatusCode(HttpStatus.SEE_OTHER);

        //設(shè)置頭信息  loginUrl跳轉(zhuǎn)到位置
        response.getHeaders().set("Location",loginUrl);

        //響應(yīng)回去 進(jìn)行跳轉(zhuǎn)
        return response.setComplete();
    }

//擁有normal或者admin角色的用戶都可以方法helloUser()方法首启。
@PreAuthorize("hasRole('normal') AND hasRole('admin')") 
   public String helloUser() {
    return "hello,user";
}

@PreAuthorize(value = "#oauth2.hasAnyScope('A','B','C','D')")//添加機(jī)構(gòu)編碼權(quán)限,判斷該機(jī)構(gòu)是否有權(quán)限調(diào)用
@PreAuthorize(value="isAuthenticated()")//添加登錄權(quán)限判斷撤摸,登錄才可以調(diào)用
public String getInformation(){
return info;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毅桃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子准夷,更是在濱河造成了極大的恐慌钥飞,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衫嵌,死亡現(xiàn)場離奇詭異读宙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)楔绞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門结闸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人墓律,你說我怎么就攤上這事膀估。” “怎么了耻讽?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵察纯,是天一觀的道長。 經(jīng)常有香客問我针肥,道長饼记,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任慰枕,我火速辦了婚禮具则,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘具帮。我一直安慰自己博肋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布蜂厅。 她就那樣靜靜地躺著匪凡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掘猿。 梳的紋絲不亂的頭發(fā)上病游,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音稠通,去河邊找鬼衬衬。 笑死买猖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滋尉。 我是一名探鬼主播玉控,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼狮惜!你這毒婦竟也來了奸远?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤讽挟,失蹤者是張志新(化名)和其女友劉穎懒叛,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耽梅,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薛窥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眼姐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诅迷。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖众旗,靈堂內(nèi)的尸體忽然破棺而出罢杉,到底是詐尸還是另有隱情,我是刑警寧澤贡歧,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布滩租,位于F島的核電站,受9級特大地震影響利朵,放射性物質(zhì)發(fā)生泄漏律想。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一绍弟、第九天 我趴在偏房一處隱蔽的房頂上張望技即。 院中可真熱鬧,春花似錦樟遣、人聲如沸而叼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葵陵。三九已至,卻和暖如春屿衅,著一層夾襖步出監(jiān)牢的瞬間埃难,已是汗流浹背莹弊。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工涤久, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涡尘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓响迂,卻偏偏與公主長得像考抄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蔗彤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355