简体   繁体   English

从 spring 引导中的 jwt 获取附加属性

[英]get additional attributes from jwt in spring boot

I am developing a spring boot service that is protected by keycloak and it accepts jwt bearer token for authentication.我正在开发一个受 keycloak 保护的 spring 引导服务,它接受 jwt 不记名令牌进行身份验证。

I also configured swagger and registered it as a public client, so when I make a request from swagger-ui a keycloak generates a JWT token which swagger then uses for authentication when making requests to the api. I also configured swagger and registered it as a public client, so when I make a request from swagger-ui a keycloak generates a JWT token which swagger then uses for authentication when making requests to the api.

I also created 2 additional private mappers for user information.我还为用户信息创建了 2 个额外的私有映射器。 Now I'd like to get those 2 attributes inside my spring controller.现在我想在我的 spring controller 中获取这两个属性。

Bellow is my example code.贝娄是我的示例代码。
I feel a bit lost in spring security and various ways of doing stuff (spring security / oauth2 / keycloak etc....) so some explanation along the solution would be really appreciated.我对 spring 安全性和各种做事方式(spring security / oauth2 / keycloak 等)感到有点迷失,所以对解决方案的一些解释将不胜感激。

pom.xml pom.xml

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

        <!-- spring security test -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- KeyCloak -->
        <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-spring-boot-2-starter -->
        <!-- https://stackoverflow.com/questions/50243088/keycloak-4-0-0-beta-2-with-spring-boot-2 -->      <!---->
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-2-starter</artifactId>
            <version>4.0.0.Final</version>
        </dependency>

Spring Security config Spring 安全配置

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends KeycloakWebSecurityConfigurerAdapter  {

    @Autowired
    public void configureGlobal(
      AuthenticationManagerBuilder auth) throws Exception {

        KeycloakAuthenticationProvider keycloakAuthenticationProvider
         = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
          new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    public KeycloakSpringBootConfigResolver 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("/test*")
          .hasRole("user")
          .anyRequest()
          .permitAll();
    }



}

example controller示例 controller

    @RequestMapping(value = "HelloWorld1", method = RequestMethod.GET)
    @ApiOperation(value = "HelloWorld1", produces = "application/json")
    @ResponseBody
    public String HelloWorld1(Principal principal) {
//I'd like something like this to work:
//String attr = principal.getAttribute("attribute1");
//
        System.out.println(principal.getName());
        RestTemplate restTemplate = new RestTemplate();
        String text = restTemplate.getForObject(
            "http://localhost:8080/test/test/HelloWorld", String.class);
        return "Hello " + principal.getName() + " " +  "it works! \n " + text;
    }

I don't know for the Keycloak Spring adapter but you can do this with the Spring Boot module for Spring Security OAuth2.我不知道 Keycloak Spring 适配器,但您可以使用 Spring 引导模块 Spring 安全 OAuth2 执行此操作。 There is a good tutorial given at one of the Spring I/O 2019 labs showing 1) how to authorize based on some JWT claim (or claim retrieved from UserInfo endpoint) in Spring Security DSL; Spring I/O 2019 实验室之一提供了一个很好的教程,显示 1) 如何根据 Z38008DD81C2F4D7985ECF6E0CE 中的一些 JWT 声明(或从 UserInfo 端点检索的声明)进行授权; 2) how to extract attributes to use them in a web controller, web page, etc. See section "Implement the client" there. 2) 如何提取属性以在 web controller、web 页面等中使用它们。请参见那里的“实现客户端”部分。

Basically, you need to add this dependency to your project (Gradle syntax, please adapt for Maven):基本上,你需要在你的项目中添加这个依赖(Gradle语法,请适应Maven):

implementation('org.springframework.boot:spring-boot-starter-oauth2-client')

Then:然后:

Authorization in Spring Security DSL (HTTP Security) based on OIDC attributes/claims基于 OIDC 属性/声明的 Spring 安全 DSL(HTTP 安全)中的授权

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .anyRequest()
        .fullyAuthenticated()
        .and()
        .oauth2Client()
        .and()
        .oauth2Login()
        .userInfoEndpoint()
        .userAuthoritiesMapper(userAuthoritiesMapper());
  }

  private GrantedAuthoritiesMapper userAuthoritiesMapper() {
    return (authorities) -> {
      Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

      authorities.forEach(
          authority -> {
            if (authority instanceof OidcUserAuthority) {
              OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;

              OidcIdToken idToken = oidcUserAuthority.getIdToken();
              OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();

              List<SimpleGrantedAuthority> groupAuthorities =
                  userInfo.getClaimAsStringList("groups").stream()
                      .map(g -> new SimpleGrantedAuthority("ROLE_" + g.toUpperCase()))
                      .collect(Collectors.toList());
              mappedAuthorities.addAll(groupAuthorities);
            }
          });

      return mappedAuthorities;
    };
  }
}

Use OIDC claims/attributes in a web controller在 web controller 中使用 OIDC 声明/属性

@GetMapping("/")
  Mono<String> index(@AuthenticationPrincipal OAuth2User oauth2User, Model model) {

    model.addAttribute("fullname", oauth2User.getName());
    model.addAttribute(
        "isCurator",
        ((JSONArray) oauth2User.getAttributes().get("groups")).get(0).equals("library_curator"));
    ...    
}

Source: https://github.com/andifalk/oidc-workshop-spring-io-2019/tree/master/lab2#implement-the-client来源: https://github.com/andifalk/oidc-workshop-spring-io-2019/tree/master/lab2#implement-the-client

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM