在Spring Boot中使用keycloak令牌保护REST API

时间:2018-03-13 07:34:16

标签: rest spring-boot keycloak

当用户从我的项目中点击任何API端点时,它应该验证访问令牌。

如果用户将其发送到标题中,并且标题不在那里,那么它应该说未经授权。如果用户的请求具有电子邮件和密码等凭据,则应用程序应使用keycloak凭据类型生成访问令牌。

我尝试了同样的但它抛出了这样的异常:

java.lang.NullPointerException: null
    at java.util.concurrent.ConcurrentHashMap.get(Unknown Source)
    at org.keycloak.adapters.rotation.JWKPublicKeyLocator.lookupCachedKey(JWKPublicKeyLocator.java:85)
    at org.keycloak.adapters.rotation.JWKPublicKeyLocator.getPublicKey(JWKPublicKeyLocator.java:69)
    at org.keycloak.adapters.rotation.AdapterRSATokenVerifier.getPublicKey(AdapterRSATokenVerifier.java:44)
    at org.keycloak.adapters.rotation.AdapterRSATokenVerifier.verifyToken(AdapterRSATokenVerifier.java:55)
    at org.keycloak.adapters.rotation.AdapterRSATokenVerifier.verifyToken(AdapterRSATokenVerifier.java:37)
    at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticateToken(BearerTokenRequestAuthenticator.java:87)
    at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticate(BearerTokenRequestAuthenticator.java:82)
    at org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:68)
    at org.keycloak.adapters.undertow.AbstractUndertowKeycloakAuthMech.keycloakAuthenticate(AbstractUndertowKeycloakAuthMech.java:110)
    at org.keycloak.adapters.undertow.ServletKeycloakAuthMech.authenticate(ServletKeycloakAuthMech.java:92)
    at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:244)
    at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:230)
    at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:124)
    at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:99)
    at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:92)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.keycloak.adapters.undertow.ServletPreAuthActionsHandler.handleRequest(ServletPreAuthActionsHandler.java:69)
    at org.keycloak.adapters.undertow.ServletPreAuthActionsHandler.handleRequest(ServletPreAuthActionsHandler.java:69)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:119)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:285)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:264)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:175)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:209)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:802)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
我正在使用的代码如下所示。

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
      private DataSource dataSource;

     @Autowired
       public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
          keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
          auth.authenticationProvider(keycloakAuthenticationProvider);
       }

      @Override
      protected void configure(HttpSecurity http) throws Exception {
        http
        .addFilterAfter(new SecurityFilter(), BasicAuthenticationFilter.class).exceptionHandling()
        .authenticationEntryPoint(
                (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)).
        and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/api/user/signout")
          .permitAll()
          .and().httpBasic().disable();
      }
      @Override
      public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
      }

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

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


@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.exceptionHandling()
            .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and().csrf().disable().headers().frameOptions().disable()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().authorizeRequests()
            .antMatchers("/api/**").authenticated()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN);

        // @formatter:on
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
         resources.resourceId("test");
            RemoteTokenServices tokenServices = new RemoteTokenServices();
            tokenServices.setCheckTokenEndpointUrl(
                "serverurl");
            tokenServices.setClientId("test");
            tokenServices.setClientSecret("secret");
            tokenServices.setAccessTokenConverter(new KeycloakAccessTokenConverter());
            resources.tokenServices(tokenServices);
    }

    private class KeycloakAccessTokenConverter extends DefaultAccessTokenConverter {

        @Override
        public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
            OAuth2Authentication oAuth2Authentication = super.extractAuthentication(map);
            Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>) oAuth2Authentication.getOAuth2Request().getAuthorities();
            if (map.containsKey("realm_access")) {
                Map<String, Object> realm_access = (Map<String, Object>) map.get("realm_access");
                if(realm_access.containsKey("roles")) {
                    ((Collection<String>) realm_access.get("roles")).forEach(r -> authorities.add(new SimpleGrantedAuthority(r)));
                }
            }
            return new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(),oAuth2Authentication.getUserAuthentication());
        }
    }   
}

0 个答案:

没有答案