cas5.3.2單點登錄-Cas Server自定義Oauth2.0的用戶信息

前言

目前我們系統中,用戶登陸,API調用是融合在一起的,API后面是調用各個dubbo服務。為了保證各個系統能夠鑒權,目前的做法是,用用戶登陸后,生成token,將token存在redis中,各個系統通過讀取reids的token作為驗證。

幾個問題:

  1. 登陸體系和業務代碼混合在一起,不是特別規范。
  2. 自定義的token機制,缺點很多。
  3. 所有服務都是直接讀取redis,安全性很差。
  4. 擴展性比較差。

準備

目前業務系統完全耦合在一起的,我們需要將登陸獨立出來。
很多大公司都有自己的CAS系統,這樣公司的其他系統不必要建立自己的賬號體系,直接接入CAS即可。
之前我不是特別能夠區分CAS,SSO,OAUTH2這些概念,經過了幾個星期的探索重要理清楚了。

  • SSO
    SSO是Single Sign On,一次登陸,全部訪問。對于我們來說,使用了SSO,多個系統可以完全獨立,所有系統不用關心用戶體系。
  • OAUTH2
    OAUTH2是一種授權開放協議。官網上面這么介紹.
    An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
    
    相關文章:
    https://oauth.net/
    http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
  • CAS
    CAS是Central Authentication Service的縮寫,耶魯大學開啟的一個開源項目,是企業級的SSO解決方案。
    https://apereo.github.io/cas/5.3.x/index.html

改造

基于上面的概念,以及我們的需求,我們的用戶系統有SSO和OAUTH2.0兩個功能。我們會基于CAS實現我們的功能,CAS天熱支持SSO,主要是OAUTH2.0的支持,我們查他的文檔發現他有插件可以支持。
對于環境搭建,可以參考:
https://blog.csdn.net/qq_34021712/article/details/80871015
https://blog.csdn.net/qq_34021712/article/details/82290876

正文

構建SSO和OAUTH2.0

按上面文章結合官網,我們搭建好環境。
https://apereo.github.io/cas/5.3.x/installation/OAuth-OpenId-Authentication.html
訪問下面地址
https://server.cas.com:8443/cas/oauth2.0/accessToken?grant_type=password&client_id=20180901&username=casuser&password=Mellon
得到下面結果:
access_token=AT-1-DrieDtlxv43rEiXIt2uuRvD3YFKTvCE9&expires_in=28800
我們將access_token修改放入下面地址
https://server.cas.com:8443/cas/oauth2.0/profile?access_token=AT-1-DrieDtlxv43rEiXIt2uuRvD3YFKTvCE9
得到下面結果:
{ "service": "http://localhost:8080", "attributes": {}, "id": "casuser", "client_id": "20180901" }
我們會發現沒有任何用戶信息,然后我參考cas5.3.2單點登錄-自定義返回信息給客戶端(十九) 這個文章, 發現結果沒有任何變化。

問題和解決

既然有問題,那么怎么解決?之前我走了很多彎路,原因在于兩個方面,第一,對CAS本地理解不足,第二,對于官網文檔理解不足。
首先,需要debug一下,看看問題所在,我們有兩個url,第一個是獲取accessToken,第二個是獲取用戶信息。
跟蹤獲取用戶信息,發現獲取用戶信息是從session里面獲取的,里面用戶信息就是空,那么我開始會認為是accessToken獲取的時候,會將用戶信息放入session,這里出現問題,才會導致profile沒有效果。
進一步跟蹤accessToken,發現在存儲session的時候,使用的是UsernamePasswordCredential生成的profile,而這個里面只用username和password兩個屬性。所以,你用密碼方式登錄的,session里面是不會存儲任何用戶信息。
這個時候,查看官方文檔,里面開始就有個定制模式,我一直不明白.

package org.apereo.cas.support.oauth;

@Configuration("MyOAuthConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class MyOAuthConfiguration {
  @Bean
  @RefreshScope
  public OAuth20UserProfileViewRenderer oauthUserProfileViewRenderer() {   
  ...
  }}

在跟蹤profile代碼的時候,發現OAuth20UserProfileViewRenderer是這里面的方法,才恍然大悟,官方的意思是,accessToken的時候,你不需要做任何修改,但是在獲取用戶信息的時候,你可以自定義,例如從數據庫或者 Redis里面讀取用戶信息。

代碼如下:
配置類

package com.destinym.cas.config;

import com.destinym.cas.custom.CustomOAuth20UserProfileViewRenderer;
import com.destinym.cas.mock.MockUserService;
import com.destinym.cas.service.UserService;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.support.oauth.web.views.OAuth20UserProfileViewRenderer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration("customAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CustomOAuthConfiguration {
    @Bean
    @RefreshScope
    public OAuth20UserProfileViewRenderer oauthUserProfileViewRenderer() {
        CustomOAuth20UserProfileViewRenderer customOAuth20UserProfileViewRenderer = new CustomOAuth20UserProfileViewRenderer();
        return customOAuth20UserProfileViewRenderer;
    }

    @Bean
    public UserService userService() {
        return new MockUserService();
    }
}

重新render類

package com.destinym.cas.custom;

import com.destinym.cas.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apereo.cas.support.oauth.util.OAuth20Utils;
import org.apereo.cas.support.oauth.web.views.OAuth20UserProfileViewRenderer;
import org.apereo.cas.ticket.accesstoken.AccessToken;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Map;

/**
 * Created by mengliang on 2018/12/30.
 */

@Slf4j
public class CustomOAuth20UserProfileViewRenderer implements OAuth20UserProfileViewRenderer {
    @Autowired
    private UserService userService;
    private final String ID ="id";

    @Override
    public String render(Map<String, Object> model, AccessToken accessToken) {
        try {
            String userId = (String) model.get(ID);
            if (userId != null) {
                return OAuth20Utils.jsonify(userService.findByUserName(userId));
            }
        }catch (Exception e){

        }
        return null;
    }
}

自定義用戶接口

package com.destinym.cas.service;

import java.util.Map;

/**
 * Created by mengliang on 2018/12/27.
 */

public interface UserService {
    Map<String, Object> findByUserName(String username);
}

MOCK用戶信息

package com.destinym.cas.mock;

import com.destinym.cas.service.UserService;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by mengliang on 2018/12/30.
 */
public class MockUserService implements UserService {
    @Override
    public Map<String, Object> findByUserName(String username) {
        {
            HashMap hashMap = new HashMap();
            hashMap.put("username", "casuser");
            hashMap.put("tel","18600000000");
            hashMap.put("region","china");
            return hashMap;
        }
    }
}

修改spring.factories
增加

  org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration,\
  org.apereo.cas.config.CasEmbeddedContainerTomcatFiltersConfiguration,\
  com.destinym.cas.config.CustomOAuthConfiguration

重新部署后,運行結果為

{
    "tel": "18600000000",
    "region": "china",
    "username": "casuser"
}

大功告成。具體可以參考git地址:
https://github.com/destinym/cas-oauth2-custom

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容