使用Keycloak實現安全的SpringBoot微服務

Keycloak是RedHat的開源身份和訪問管理解決方案,本文介紹如何在咱們的微服務安全模塊中使用keycloak,特別是基於SpringBoot的微服務。spring

Keycloak

它提供了身份和訪問管理的有用功能:數據庫

  • 單點登陸(SSO),身份代理和社交登陸
  • 用戶聯合
  • 客戶端適配器
  • 管理控制檯和賬戶管理控制檯。

雖然安全性是任何應用程序的一個重要方面,但安全性的實現部分是複雜和困難的。一般,它在代碼中常常被忽略或執行不當和干擾。json

開發人員須要安全服務器,容許外包和受權認證和受權方面。他們想要一種可以自動開發應用程序安全功能的工具,這一般是一項複雜的任務。後端

Keycloak是最有前途的開源IDAM(身份和訪問管理)服務器之一,它與任何技術無關,能夠在本身的基礎架構中輕鬆部署/適應。瀏覽器

Keycloak嘗試解決基於REST的Web應用程序和Web服務的單點登陸。Keycloak的最終目標是使安全性足夠簡單,以便做爲服務和應用程序中的安全模塊插入。安全功能很混亂,當開發人員手動爲本身編寫時,它會變得更危險,更容易出錯。Keycloak經過提供開箱即用的安全功能幫助咱們,而且能夠根據任何組織的個性化需求輕鬆定製。安全

Keycloak能夠幫助咱們在應用程序中引入這些功能:服務器

  • 用於登陸,註冊,管理和賬戶管理的可自定義用戶界面
  • 集成到現有LDAP和活動目錄服務器
  • 將身份驗證委託給Twitter和Github等第三方身份提供商

安裝:

有不一樣的方法來安裝keycloak。最簡單的是隻需下載Keycloak,這是一種獨立的安裝模式,只需將其解壓縮便可。你完成了!如今打開一個終端並轉到解壓縮的Keycloak服務器並導航到bin目錄 - 而後只需運行如下命令:session

./standalone.sh(bat)架構

安裝完成後,打開瀏覽器並轉到http:// localhost:8080 / auth。app

默認狀況下,Keycloak附帶一個H2數據庫,但若是你選擇RDMS,你可使用帶有RDMS的Keycloak。

因爲您是第一次運行服務器,所以您必須建立管理員用戶。讓咱們建立一個管理員用戶,其中「admin」做爲用戶名,「admin」做爲密碼。

創造一個新領域

在Keycloak中,領域是您定義客戶端的地方。這意味着這些客戶端是將由Keycloak保護的應用程序 - 多是Web應用程序或Spring Boot。

注意:'Master'是Keycloak的默認領域。讓咱們只需點擊「添加領域」按鈕便可建立新領域

建立客戶端

Spring Boot應用程序是您的客戶端。就這麼簡單。在Keycloak中,客戶端是使用Keycloak保護的應用程序。

讓咱們看看如何在Keycloak中建立客戶端:

  1. 轉到門戶網站中的「Client」菜單
  2. 單擊「建立」按鈕
  3. 爲Client-Id提供名稱。咱們稱之爲Rbi-Service。

在下一個屏幕上將全部內容保持爲默認值,您須要的只是輸入一個有效的重定向URL,Keycloak將在該應用程序中對用戶進行身份驗證時使用該URL。咱們將選擇在有效的重定向URL部分中保留http:// localhost:8081/*。

Keycloak API:

您如今可能正在使用當前項目中的REST API。別擔憂,Keycloak提供對REST API的徹底支持。實際上,它還提供了一個完整的管理控制檯,能夠經過REST API使用。

這是可能的Keycloak管理REST API列表。

對於管理REST API,有一個Java客戶端庫,能夠很容易地與Java一塊兒使用。要從您的應用程序中使用它 - 就像您對任何第三方庫所作的那樣 - 只需在項目中添加keycloak-admin-client庫的依賴項。而已。

<dependency>
  <groupId>org.keycloak</groupId>
  <artifactId>keycloak-admin-client</artifactId>
  <version>3.2.1.Final</version>
</dependency>

application.yml配置:

server:
  port: 9999

keycloak:
  url: http://localhost:8080/auth
  realm: master
  username: admin
  password: admin
  clientId: admin-cli

注意:咱們須要clientId做爲admin-cli,這由keycloak提供的全部默認客戶端ID,用於實現keycloak爲admin提供的REST端點,

REST API實現

使用REST端點在域中建立用戶有幾個步驟:

1.建立用戶:

第1步:經過getInstance()方法使用主管理員的詳細信息建立實例

Keycloak kcMaster = Keycloak.getInstance(serverUrl, masterRealm, masterUsername, masterPassword, masterClientId);

第2步:在UserRepresentation中設置用戶數據

private String userName;
private String firstName;
private String lastName;
private String email;
private String password;
private String companyName;

密碼映射到CredentialRepresentation。您必須強制用戶在首次登陸時經過如下代碼更改密碼:

credential.setTemporary(isTempPassword);
and user.setRequiredActions(Arrays.asList(ACTION_UPDATE_PASSWORD));

最後,您所要作的就是在給定領域中調用createUser:

kcMaster.realm(request.getCompanyName()).users().create(user);

因爲Keycloak擁有本身的數據庫,所以新建立的用戶信息存儲在表中:user_entity

恭喜!您剛剛使用REST端點在Keyclaok中建立了一個用戶。

2.用戶登陸訪問和刷新令牌

如今遇到一個重大挑戰:將用戶登陸到您的應用程序中

Keycloak根據您在Keycloak中配置客戶端的方式提供了幾種獲取訪問令牌的方法。Keycloak爲您提供AccessTokenResponse,它是一個基於JWT的令牌,包含訪問令牌,刷新令牌和這些屬性的相關信息。

@PostMapping(path = "/login", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
    public AccessTokenResponse getToken(@RequestBody Map<String, Object> credentials) {   
        Keycloak kc = Keycloak.getInstance(serverUrl,
                               (String  credentials.get("company"), 
                               (String) credentials.get("username"), 
                               (String) credentials.get("password"),
                               (String) credentials.get("clientId"));

                      return kc.tokenManager().getAccessToken();

    }

您能夠從新檢查詳細數據,該數據嵌入了jwt.io上的訪問令牌

Keycloak with Spring

Keycloak知道本身的API與應用程序的交互,併爲願意與Keycloak通訊的應用程序提供適配器。它已經爲Javascript,NodeJs應用程序,WildFly / EAP和Spring Boot提供了適配器。Spring-boot的keycloak依賴(源代碼)

關於安全配置:

若是您是後端開發人員並且您正在使用Spring,而且您必須處理與安全相關的任務,那麼您確定使用Spring Security。好吧,有一個好消息:有一個Keycloak Spring安全適配器,它包含在Spring Boot keycloak starter中。

若是您使用過Spring Security,那麼您可能知道SecurityConfig類擴展了WebSecurityConfigurerAdapter。這是爲建立WebSecurityConfigurer實例提供了方便的基類,而且任何使用Spring Security的應用程序都須要它。Keycloak在WebSecurityConfigurerAdapter上提供了一個包裝類,名爲KeycloakWebSecurityConfigurerAdapter。

如今讓咱們看看如何將Spring Security和Keycloak結合在一塊兒。

添加Spring Security Starter

首先,咱們須要在pom.xml中添加spring-boot-starter-security工件來獲取Spring Security庫:

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

建立SecurityConfig類

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    public KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        super.configure(http);
        http
            .authorizeRequests()
            .antMatchers("/features*").hasRole("user")
            .anyRequest().permitAll();

    }
}

讓咱們仔細看看最重要的方法:

  • configureGlobal:若是你還記得Spring Security,那麼角色的前綴是ROLE_。這也能夠在keycloak中完成,但這可能會致使其餘應用程序不知道此約定的混淆。經過更改受權機構映射器,咱們分配一個SimpleAuthorityMapper,確保不添加前綴。
  • keycloakConfigResolver:默認狀況下,Keycloak Spring Security Adapter將掃描類路徑中存在的名爲keycloak.json的文件。在這裏,咱們要提供Spring Boot屬性文件支持。
  • configure:這是咱們定義安全驗證的地方。很容易理解咱們正在使用角色「user」保護路徑「/ features」。

結論

在您的應用程序中構建安全組件老是很困難,特別是當它是基於微服務的架構時。固然有多種選擇可用於構建安全服務,但Keycloak承擔這一責任並幫助開發人員專一於產品或應用程序所需的內容。

因爲Keycloak中的每一個組件都通過了很好的嘗試和測試,所以在安全模塊方面遇到任何麻煩的可能性都很小。

Keycloak確實爲Spring開發人員提供了處理安全性的巨大潛力,特別是在開發正朝着構建微服務戰略的方向發展時。

相關文章
相關標籤/搜索