Loading

用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

posted @ 2020-05-20 17:33  yaro-feng  阅读(3154)  评论(0编辑  收藏  举报