用Keycloak保護SpringBoot Rest-Api


下載和啟動keycloak很容易,做測試用,下載后進入bin文件夾下直接用自帶腳本standalone.bat啟去就可以了

用 Keycloak UI 配置鑒權所需的client,role,user

創建rest-api的client

選擇一個reaml后,點Clients --> Create

Access Type 選confidential

rest-api 不需要重定向 Valid Redirect URIs 隨便寫一個值
image-20200515174630826.png

給rest-api創建角色

給rest-api 創建一個角色叫rest-api-user
image-20200515175547349.png

創建用戶api-user

創建一個叫api-user的用戶

image-20200515180109227.png

給api-user分配角色

切到 role mappings 選項卡 在client roles 搜索到自己的rest-api,選擇角色,點擊add selected
image-20200515180547638.png

給api-user 設置密碼

image-20200515180845787.png

去掉 update password

在Required User Actions中關掉 update password點save

image-20200515180952119.png

創建另一個client叫 rest-api-client 用於獲取token訪問應用

點擊圖中第1步再點創建后,

進入第2步選confidential

打開第3步Service Accounts Enabled開關

api沒有頁面第4步可以隨意寫

點擊保存后會出現圖中第5步的選項卡

image-20200515181501872.png

給client 添加角色

1點service account roles選項卡后

2搜出rest-api

3選擇role

4添加並保存

image-20200515181853499.png

Get Token

配置完以上步驟可以來獲取token了

1 用POST方法 訪問 localhost:8080/auth/realms/cvc/protocol/openid-connect/token

2 body 格式選 application/x-www-form-urlencoded 添加參數

#client
grant_type:client_credentials
client_id:rest-api-client
client_secret:9fa7a96c-c9d5-485c-91b5-ec08d5af0542

#user
grant_type:password
username:api-user
password:12345
client_id:rest-api-client

image-20200515183102677.png

把token復制到jwt.io中可以解析看到角色

image-20200515183630056.png

SpringBoot編寫

創建SpringBoot項目

添加庫

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
            <version>7.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-security-adapter</artifactId>
            <version>7.0.0</version>
        </dependency>

增加RestController

@RestController
public class HomeController {
    private final HttpServletRequest request;

    @Autowired
    public HomeController(HttpServletRequest request) {
        this.request = request;
    }

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

配置類

import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class KeycloakConfig {

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

import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;


@KeycloakConfiguration
public class KeycloakSecurityConfigurer  extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
        grantedAuthorityMapper.setPrefix("ROLE_");

        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
        auth.authenticationProvider(keycloakAuthenticationProvider);

    }


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


    @Bean
    @Override
    @ConditionalOnMissingBean(HttpSessionManager.class)
    protected HttpSessionManager httpSessionManager() {
        return new HttpSessionManager();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers("/hello*").hasAnyRole( "rest-manager", "rest-api-user")
                .anyRequest().permitAll()
                .and().csrf().disable();
    }
}

application配置文件

keycloak:
  auth-server-url: http://localhost:8080/auth
  disable-trust-manager: true
  principal-attribute: preferred_username
  public-client: false
  realm: cvc
  resource: reactor-manager
  use-resource-role-mappings: true

keycloak的地址如果是不受信任的https(如自簽名ssl)可以設置 disable-trust-manager=true來訪問

開啟keycloak.use-resource-role-mappings=true配置后就是要配置到client下面role去驗證
配置文件的一些可選項可參考文檔:
https://www.keycloak.org/docs/latest/securing_apps/#java-adapters

{
  "resource_access": {
    "rest-api": {
      "roles": [
        "rest-api-user"
      ]
    }

從jwt解析可以看到token擁有client為rest-api下的rest-api-user的role

驗證api保護

把token填寫到 token處

image-20200515183448274.png

開啟 service_accounts

https://www.keycloak.org/docs/latest/server_admin/index.html#_service_accounts

配置 java-adapter

https://www.keycloak.org/docs/latest/securing_apps/#java-adapters

參考

https://www.thomasvitale.com/spring-security-keycloak/

http://m.lanhusoft.com/Article/740.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM