当前位置: 首页 > 知识库问答 >
问题:

在Spring引导中从jwt获取附加属性

王波
2023-03-14

我正在开发一个Spring Boot服务,它受Key斗篷保护,并接受jwt承载令牌进行身份验证。

我还配置了swagger并将其注册为公共客户端,因此当我从swagger ui发出请求时,KeyClope会生成一个JWT令牌,然后swagger在向api发出请求时使用该令牌进行身份验证。

我还为用户信息创建了另外两个私有映射器。现在我想在我的spring控制器中获得这两个属性。


我觉得有点迷失在Spring安全和各种方法中(Spring安全/oAuth2/keyCloak等...),所以对解决方案的一些解释将是非常感谢的。

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配置

@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();
    }



}

示例控制器

    @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;
    }

共有1个答案

秦鸿羽
2023-03-14

我不知道KeyClope Spring适配器的具体情况,但您可以使用Spring SecurityOAuth2的Spring Boot模块来实现这一点。其中一个Spring I/O 2019实验室提供了一个很好的教程,展示了1)如何基于Spring Security DSL中的某个JWT声明(或从UserInfoendpoint检索到的声明)进行授权;2) 如何提取属性以在web控制器、网页等中使用这些属性。请参见此处的“实现客户端”一节。

基本上,您需要将此依赖项添加到项目中(Gradle语法,请适应Maven):

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

然后:

@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;
    };
  }
}
@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"));
    ...    
}

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

 类似资料:
  • 我想在spring boot web Project中使用来自Application.Properties的@Value注释获取值。我认为我可以使用@value注释,因为我认为application.properties中的变量是动态加载的。但是当我只写@value注释时,它就不起作用了。 我在申请中有一个属性。poperties 我如何解决这个问题??

  • 在我的应用程序中,我有以下属性文件: application.properties application-prod.properties 在里面我有同样的财产 Spring数据源。password=my dev password#用于默认的 spring。数据源。password=${PROD_DATABASE_password}#用于PROD文件 在服务器上,我像这样运行应用程序: java-

  • 我使用自动配置(仅通过注释)运行Spring启动和kafka,并在.yaml文件中定义了道具,即: 它工作得很好,spring maps即字段group-id正确。 但是当我尝试使用相同的yaml文件手动配置Kafka(使用消费者工厂和消费者配置)时,我遇到了问题。在类中,消费者配置Kafka属性以 命名。在名称中,而不是 _ 即: 所以我不能把它们加载到map中,然后把map传递给Consume

  • 如何从Cloud Config服务器实例配置基本的Spring Boot属性?显然,与配置服务器相关的Spring boot属性(即cloud.config.uri,*.username,*.password)必须在bootstrap.yml中 下面的其他属性是什么:https://docs.spring.io/spring-boot/docs/current/reference/html/com

  • 我必须得到一个环境变量,我不能注射。 我无法注入环境中的basUrl。 有人能告诉我怎么做吗? 我读了以下几页,我是初学者,因为我什么都不懂。https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.htmlhttps://www.mkyong.com/spring-bo

  • 附录 B 引导加载器(boot loader) 当 x86 PC 启动时,它执行的是一个叫 BIOS 的程序。BIOS 存放在非易失存储器中,BIOS 的作用是在启动时进行硬件的准备工作,接着把控制权交给操作系统。具体来说,BIOS 会把控制权交给从引导扇区(用于引导的磁盘的第一个512字节的数据区)加载的代码。引导扇区中包含引导加载器——负责内核加载到内存中。BIOS 会把引导扇区加载到内存 0