下載和啟動keycloak很容易,做測試用,下載后進入bin文件夾下直接用自帶腳本standalone.bat啟去就可以了
用 Keycloak UI 配置鑒權所需的client,role,user
創建rest-api的client
選擇一個reaml后,點Clients --> Create
Access Type 選confidential
rest-api 不需要重定向 Valid Redirect URIs 隨便寫一個值
給rest-api創建角色
給rest-api 創建一個角色叫rest-api-user
創建用戶api-user
創建一個叫api-user的用戶
給api-user分配角色
切到 role mappings 選項卡 在client roles 搜索到自己的rest-api,選擇角色,點擊add selected
給api-user 設置密碼
去掉 update password
在Required User Actions中關掉 update password點save
創建另一個client叫 rest-api-client 用於獲取token訪問應用
點擊圖中第1步再點創建后,
進入第2步選confidential
打開第3步Service Accounts Enabled開關
api沒有頁面第4步可以隨意寫
點擊保存后會出現圖中第5步的選項卡
給client 添加角色
1點service account roles選項卡后
2搜出rest-api
3選擇role
4添加並保存
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
把token復制到jwt.io中可以解析看到角色
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處
開啟 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