允许OPTIONS HTTP方法执行oauth/token请求

Woj*_*cki 37 spring oauth spring-security cors oauth-2.0

我正在尝试为我的角应用程序启用oauth2令牌获取.我的配置工作正常(身份验证对所有请求都正常工作,令牌提取工作正常)但有一个问题.

CORS请求要求在GET之前将OPTIONS请求发送到服务器.更糟糕的是,该请求不包含任何身份验证标头.我希望此请求始终返回200状态,而无需在服务器上进行任何身份验证.可能吗?也许我错过了什么

我的春季安全配置:

@Configuration
@EnableWebSecurity
@EnableAuthorizationServer
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);

@Inject
private UserService userService;

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

@Bean
public DefaultTokenServices tokenServices() {
    DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
    defaultTokenServices.setTokenStore(tokenStore());
    return defaultTokenServices;
}

@Bean
public WebResponseExceptionTranslator webResponseExceptionTranslator() {
    return new DefaultWebResponseExceptionTranslator() {

        @Override
        public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
            ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
            OAuth2Exception body = responseEntity.getBody();
            HttpHeaders headers = new HttpHeaders();
            headers.setAll(responseEntity.getHeaders().toSingleValueMap());
            headers.set("Access-Control-Allow-Origin", "*");
            headers.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            headers.set("Access-Control-Max-Age", "3600");
            headers.set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            return new ResponseEntity<>(body, headers, responseEntity.getStatusCode());
        }

    };
}

@Bean
public AuthorizationServerConfigurer authorizationServerConfigurer() {
    return new AuthorizationServerConfigurer() {

        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
            oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator());
            security.authenticationEntryPoint(oAuth2AuthenticationEntryPoint);
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("secret-client")
                    .secret("secret")
                    .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                    .authorities("ROLE_LOGIN")
                    .scopes("read", "write", "trust")
                    .accessTokenValiditySeconds(60 * 60 * 12); // 12 hours
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenServices(tokenServices());
            endpoints.authenticationManager(authenticationManager());
        }
    };
}

@Override
protected AuthenticationManager authenticationManager() throws Exception {
    return new AuthenticationManager() {

        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            log.warn("FIX ME: REMOVE AFTER DEBUG!!!!!!!!!!!!");                
            log.debug("authenticate: " + authentication.getPrincipal() + ":" + authentication.getCredentials());
            final Collection<GrantedAuthority> authorities = new ArrayList<>();
            WomarUser user = userService.findUser(authentication.getPrincipal().toString(), authentication.getCredentials().toString());
            for (UserRole userRole : user.getRoles()) {
                authorities.add(new SimpleGrantedAuthority(userRole.getName()));

            }
            return new UsernamePasswordAuthenticationToken(user.getLogin(), user.getPassword(), authorities);
        }

    };
}

@Bean
public OAuth2AuthenticationManager auth2AuthenticationManager() {
    OAuth2AuthenticationManager oAuth2AuthenticationManager = new OAuth2AuthenticationManager();
    oAuth2AuthenticationManager.setTokenServices(tokenServices());
    return oAuth2AuthenticationManager;
}

@Bean
public OAuth2AuthenticationProcessingFilter auth2AuthenticationProcessingFilter() throws Exception {
    OAuth2AuthenticationProcessingFilter oAuth2AuthenticationProcessingFilter = new OAuth2AuthenticationProcessingFilter();
    oAuth2AuthenticationProcessingFilter.setAuthenticationManager(auth2AuthenticationManager());
    return oAuth2AuthenticationProcessingFilter;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
    oAuth2AuthenticationEntryPoint.setRealmName("realmName");
    oAuth2AuthenticationEntryPoint.setTypeName("Basic");
    oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator());
    http
            .antMatcher("/**").httpBasic()
            .authenticationEntryPoint(oAuth2AuthenticationEntryPoint)
            .and().addFilterBefore(auth2AuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/rest/womar/admin/**").hasRole("ADMIN")
            .antMatchers("/rest/womar/**").hasRole("USER");
}
Run Code Online (Sandbox Code Playgroud)

}

角度要求:

var config = {
params: {
    grant_type: 'password',
    username: login,
    password: password

},
headers: {
    Authorization: 'Basic ' + Base64.encode('secret-client' + ':' + 'secret')
}
};
$http.get("http://localhost:8080/oauth/token", config)
    .success(function(data, status) {
        $log.log('success');
        $log.log(data);
        $log.log(status);
    })
    .error(function(data, status) {
        $log.log('error');
        $log.log(data);
        $log.log(status);
    });
Run Code Online (Sandbox Code Playgroud)

idu*_*sun 42

@EnableAuthorizationServer被添加的是http的安全配置像端点/oauth/token,/oauth/token_key在为了0等那么,你应该做的是定义一个http安全规则/oauth/token端点只为OPTIONS HTTP方法,它是在一个更高阶.

像这样的东西:

@Order(-1)
@Configuration
public class MyWebSecurity extends WebSecurityConfigurerAdapter {
   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
          .authorizeRequests()
          .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨,你可以看看我的github存储库,我在那里用角度和弹簧进行一些实验工作.我的令牌处理工作正常.https://github.com/idursun/spring-and-angular (4认同)
  • 我有同样的问题,但这个解决方案确实产生了另一个问题.我的问题的解决方案是停止处理请求的过滤器链,以便AuthServer根本看不到OPTIONS预检请求!您可以在此处查看我的解决方案:http://stackoverflow.com/questions/30632200/standalone-spring-oauth2-jwt-authorization-server-cors/30638914#30638914 (3认同)
  • 嗨,我遇到了同样的问题。即使此解决方案也未授权/不允许向OAuth /令牌发送OPTIONS请求 (2认同)
  • 看起来,拦截OPTIONS处理的正确方法是通过HttpSecurity的requestMatchers方法。这样,我们不会影响其他请求,而不像`authorizeRequests()`中的过滤器一样:protected void configure(HttpSecurity http)引发异常{http .requestMatchers().antMatchers(HttpMethod.OPTIONS,“ / oauth / token”).and( ).cors().and()。csrf()。disable(); } (2认同)

cam*_*ser 5

我正在使用idursun提出的解决方案。OPTION调用开始起作用,但是Access-Control-Allow-Origin仍然存在问题。

这个过滤器实现绝对为我工作:

独立的Spring OAuth2 JWT授权服务器+ CORS