統一認證 - Apereo CAS 客戶端的集成以及小結

前兩篇介紹了Apereo CAS以及服務器端的安裝,但還不夠完整,服務端還沒有Application真正用起來呢!這篇文章將介紹怎麼用起來

集成的目的

客戶端我們想要與Apereo CAS做什麼集成呢?回顧一下Apereo CAS是做什麼的?Apereo CAS的一個功能就是單點登錄,統一的登錄登出接口與頁面,讓系統中的模塊只需要關注在業務點,而把安全認證的功能交給統一認證來做。所以客戶端的集成主要是單點登錄的集成,客戶端指定需要做安全認證的頁面,然後Apereo CAS的安全包檢測校驗用戶登錄情況,並自動與CAS登錄頁面進行跳轉交互。

客戶端的配置

Apereo CAS提供了Springboot的包,可以讓我們的集成些微方便了那麼一丟丟!首先我們創建一個Springboot的application,裏面帶了Apereo CAS start的依賴

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-cas</artifactId>
</dependency>

同時在application.properties文件裏面指定啓動的端口 server.port = 9000

有了Apereo CAS的包之後,我們就可以進行代碼的配置。客戶端的配置按照SpringSecurity的安全檢驗流程進行的:

  1. 用戶嘗試打開一個受保護的url,比如/admin/user
  2. AuthenticationEntryPoint被觸發了,把用戶重定向到配置好的CAS登錄頁面https://localhost:6443/cas
  3. 用戶輸入用戶名密碼,登錄成功後, CAS會跳轉回application指定的回調url http://localhost:9000/login/cas, 並帶上ticket作爲查詢參數
  4. CasAuthenticationFilter一直在監聽/login/cas這個路徑,當發現有請求後,它會觸發CasTicketValidator,由CasTickerValidator檢驗ticket的有效性
  5. 當ticket也驗證成功後,用戶將會被跳轉回原來請求的受保護url

下面代碼大致描述了這個過程:

@Bean
public ServiceProperties serviceProperties() {
    ServiceProperties serviceProperties = new ServiceProperties();
    serviceProperties.setService("http://localhost:9000/login/cas");
    serviceProperties.setSendRenew(false);
    return serviceProperties;
}
 
@Bean
@Primary
public AuthenticationEntryPoint authenticationEntryPoint(
  ServiceProperties sP) {
  
    CasAuthenticationEntryPoint entryPoint
      = new CasAuthenticationEntryPoint();
    entryPoint.setLoginUrl("https://localhost:6443/cas/login");
    entryPoint.setServiceProperties(sP);
    return entryPoint;
}
 
@Bean
public TicketValidator ticketValidator() {
    return new Cas30ServiceTicketValidator(
      "https://localhost:6443/cas");
}
 
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
  
    CasAuthenticationProvider provider = new CasAuthenticationProvider();
    provider.setServiceProperties(serviceProperties());
    provider.setTicketValidator(ticketValidator());
    provider.setUserDetailsService(
      s -> new User("casuser", "Mellon", true, true, true, true,
        AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
    provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
    return provider;
}
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    private AuthenticationProvider authenticationProvider;
    private AuthenticationEntryPoint authenticationEntryPoint;
    private SingleSignOutFilter singleSignOutFilter;
    private LogoutFilter logoutFilter;
 
    @Autowired
    public SecurityConfig(CasAuthenticationProvider casAuthenticationProvider, AuthenticationEntryPoint eP,
                          LogoutFilter lF
                          , SingleSignOutFilter ssF
    ) {
        this.authenticationProvider = casAuthenticationProvider;
        this.authenticationEntryPoint = eP;
 
        this.logoutFilter = lF;
        this.singleSignOutFilter = ssF;
 
    }
     
    // ...
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.authenticationProvider(authenticationProvider);
    }
 
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
      return new ProviderManager(Arrays.asList(authenticationProvider));
    }
 
    @Bean
    public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sP) throws Exception {
      CasAuthenticationFilter filter = new CasAuthenticationFilter();
      filter.setServiceProperties(sP);
      filter.setAuthenticationManager(authenticationManager());
      return filter;
    }
}

下面這個文件配置了application中所有/secured/*,login的URL都是受保護資源,都要經過CAS認證過纔可以訪問:

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http
        .authorizeRequests()
        .regexMatchers("/secured.*", "/login")
        .authenticated()
        .and()
        .authorizeRequests()
        .regexMatchers("/")
        .permitAll()
        .and()
        .httpBasic()
        .authenticationEntryPoint(authenticationEntryPoint);
    }
    // ...
}

服務端Apereo CAS的配置

跟所有統一認證平臺一樣,所有application想要跟CAS做集成的,都需要在CAS配置相應的參數纔可以使用。Apereo CAS提供了很多配置的方式,有YML,JSON, MongoDB以及其他(可查官網)。但高度自由的CAS一如既往的,沒有提供可視化操作的界面。比如我們採用JSON的方式。首先我們需要通知Apereo CAS我們採用的是JSON的方式,並通知JSON文件的路徑在哪裏

cas.serviceRegistry.initFromJson=true
cas.serviceRegistry.config.location=classpath:/services

然後我們在這個目錄裏面,創建一個對應的JSON文件,保存我們的客戶端信息,爲了方面管理,建議文件名爲 application_id.json, 比如"secureApp_9991.json", 內容如下:

{
    "@class" : "org.apereo.cas.services.RegexRegisteredService",
    "serviceId" : "^http://localhost:9000/login/cas",
    "name" : "CAS Spring Secured App",
    "description": "This is a Spring App that usses the CAS Server for it's authentication",
    "id" : 19991,
    "evaluationOrder" : 1
}

第一次配置從JSON加載客戶端配置的話,需要重啓Apereo CAS。之後再加新的客戶端的話就不用再重啓,Apereo CAS會自動監測這個文件夾的變動

小結

至此我們對於Apereo CAS就有了一個稍微完整一點點的瞭解,從服務端安裝部署,到配置,以及客戶端如何集成等。但從這個短時間的學習來看,如果企業已經重度使用了Apereo CAS,那相信它可以很好地服務支撐企業的應用。但如果是新的項目,特別是項目週期比較緊張的項目,並且團隊之前沒有對統一認證有技術積累的話,不是很建議採用Apereo CAS,這些細微的配置以及無所不在的隱藏功能,會讓你給項目經理催死的! 後面我會介紹另外一個統一認證的框架,個人感覺能彌補Apereo CAS的短板的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章