java - 为什么 PermitAll() 不起作用并且它要求在请求中提供身份验证对象?

标签 java spring-security spring-security-oauth2

我正在使用 spring security oauth2 实现授权。我有单独的授权服务器和资源服务器。

资源服务器代码:

OauthResourceServerConfig.java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor;
import org.springframework.security.oauth2.provider.authentication.TokenExtractor;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;


@Configuration
@EnableResourceServer
public class OAuthResourceConfig extends ResourceServerConfigurerAdapter {

    private TokenExtractor tokenExtractor = new BearerTokenExtractor();

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
        exceptionHandling()
        .and()
        .csrf()
        .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
        .disable()
        .headers()
        .frameOptions().disable().disable()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/secure/**").permitAll() //<<<<<<<<<<<<<<<<<<<<<<<<<<
        .antMatchers("/hello/**").authenticated(); // <<<<<<<<<<<<<<<<<<<<<
    }

    @Bean
    public AccessTokenConverter accessTokenConverter() {
        return new CustomAccessTokenConverter();
    }

    @Bean
    @Primary
    public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl,
            final @Value("${auth.server.clientId}") String clientId,
            final @Value("${auth.server.clientsecret}") String clientSecret) {

        final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
        remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl);
        remoteTokenServices.setClientId(clientId);
        remoteTokenServices.setClientSecret(clientSecret);
        remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
        return remoteTokenServices;
    }
}

Controller :

@Controller
@RequestMapping("/secure")
public class SecureController {

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public String sayHello() {


        return "Secure Hello!";
    }

}

授权服务器代码:

Oauth2Configuration.java

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import com.pedagogy.authserver.security.Authorities;

@Configuration
public class OAuth2Configuration {


    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {

        private static final String ENV_OAUTH = "authentication.oauth.";
        //private static final String PROP_CLIENTID = "clientid";
        //private static final String PROP_SECRET = "secret";
        private static final String PROP_ACCESS_TOKEN_VALIDITY_SECONDS = "accessTokenValidityInSeconds";
        private static final String PROP_REFRESH_TOKEN_VALIDITY_SECONDS = "refreshTokenValidityInSeconds";

        private RelaxedPropertyResolver propertyResolver;

        @Autowired
        private DataSource dataSource;

        @Autowired
        private CustomUserDetailService userDetailsService;

        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints.tokenStore(tokenStore())
                     .userDetailsService(userDetailsService)
                     .tokenEnhancer(tokenEnhancer())
                     .accessTokenConverter(accessTokenConverter())
                     .authenticationManager(authenticationManager);
        }

        @Bean
        public TokenEnhancer tokenEnhancer() {
           return new CustomTokenEnhancer();
        }

        @Bean
        public DefaultAccessTokenConverter accessTokenConverter() {
            return new DefaultAccessTokenConverter();
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer)
                throws Exception {
            oauthServer
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
        }


        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                    .inMemory()

                    .withClient("clientId")
                    .scopes("read", "write")
                    .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
                    .authorizedGrantTypes("password", "refresh_token")
                    .accessTokenValiditySeconds(propertyResolver.getProperty(PROP_ACCESS_TOKEN_VALIDITY_SECONDS, Integer.class, 80))
                    .refreshTokenValiditySeconds(propertyResolver.getProperty(PROP_REFRESH_TOKEN_VALIDITY_SECONDS, Integer.class, 180))

                    .and().inMemory()
                    .withClient("clientid")
                    .scopes("read", "write")
                    .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
                    .authorizedGrantTypes("client_credentials")
                    .secret("secret");

        }

        @Override
        public void setEnvironment(Environment environment) {
            this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
        }

    }

}

安全配置.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;


@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailService userDetailsService;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider
          = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(encoder());
        return authProvider;
    }

    @Bean
    public ShaPasswordEncoder encoder() {
        return new ShaPasswordEncoder(256);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {}

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable();

    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
    private static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {

        public GlobalSecurityConfiguration() {
        }
        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            return new OAuth2MethodSecurityExpressionHandler();
        }

    }

}

当我制作http://localhost:8889/secure?lang=en时调用 postman ,我收到错误:

{
    "error": "unauthorized",
    "error_description": "An Authentication object was not found in the SecurityContext"
}

我已经使用 permitAll() 配置了 /secure 端点,因此它不需要传递访问 token 。为什么在这种情况下 PermitAll() 不起作用?

我也尝试过允许所有请求,但它也不起作用,并且在响应中面临相同的错误。

@Override
    public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().permitAll();
}

最佳答案

我已经配置了以下网址,它现在正在运行。

.antMatchers("/hello/").permitAll()
                .antMatchers("/secure3/").permitAll()
                .antMatchers("/secure/**").authenticated()
                .antMatchers("/secure2/**").authenticated();

我已添加这些安全* Controller 进行测试并验证其是否正常工作。

关于java - 为什么 PermitAll() 不起作用并且它要求在请求中提供身份验证对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45120255/

相关文章:

java - 为什么 Scala 从对象的 main 方法而不是类的静态 main 方法开始?

java - 为什么 Java 类可以在方法中声明并初始化该类的对象?

java - if 语句断言True/assertFalse

java - 使用 Jetty 进行 HTTP/2 优先级和依赖性测试

oauth-2.0 - 具有 oauth2 和 spring security 的 AWS api 网关

java - Spring 5 Security 支持 $2y$ bcrypt 哈希版本吗?

java - Spring 启动: How to auto login after user registration?

java - Spring Security Java 配置问题

spring - hasRole 总是返回 403

java - 如何更改 ClientCredentialsResourceDetails 发出的请求的内容类型?