Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/421.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 不允许使用Spring Security OAuth2 JWT CORS_Javascript_Java_Spring Boot_Spring Security_Spring Security Oauth2 - Fatal编程技术网

Javascript 不允许使用Spring Security OAuth2 JWT CORS

Javascript 不允许使用Spring Security OAuth2 JWT CORS,javascript,java,spring-boot,spring-security,spring-security-oauth2,Javascript,Java,Spring Boot,Spring Security,Spring Security Oauth2,我的CORS配置有问题。我在YT上看了一些教程和视频,我在这里寻找StackOverflow的帮助,但没有任何帮助。 我有两个后端项目(第一个是带有OAuth2和JWT的one-Spring Boot 1.5.9,第二个是带有Spring Security 5基本身份验证的one-Spring Boot 2.0.0 M7),我的朋友使用React作为前端。在这两种情况下,我都有相同的问题-当我们想要登录时,服务器会以401 HTTP状态响应,并显示以下消息: 加载失败http://localho

我的CORS配置有问题。我在YT上看了一些教程和视频,我在这里寻找StackOverflow的帮助,但没有任何帮助。 我有两个后端项目(第一个是带有OAuth2和JWT的one-Spring Boot 1.5.9,第二个是带有Spring Security 5基本身份验证的one-Spring Boot 2.0.0 M7),我的朋友使用React作为前端。在这两种情况下,我都有相同的问题-当我们想要登录时,服务器会以401 HTTP状态响应,并显示以下消息:
加载失败http://localhost:8080/oauth/token: 飞行前响应的HTTP状态代码401无效

案例1(弹簧靴1.5.9 OAuth2 JWT)

在这个项目中,我有

扩展WebSecurityConfigureAdapter的SecurityConfig类

我的AuthorizationServerConfigurerAdapter的实现

ResourceServerConfig的设计与实现

我的ResourceServerConfig类如下所示:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

private static final String RESOURCES_IDS = "ResourceId";
private static final String SECURITY_REALM = "Spring Boot Realm";

private final TokenStore tokenStore;

@Autowired
public ResourceServerConfig(TokenStore tokenStore) {
    this.tokenStore = tokenStore;
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) {
    resources.resourceId(RESOURCES_IDS)
            .tokenStore(tokenStore);
}

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers(REGISTER_USER + "/**").permitAll()
            .antMatchers(HttpMethod.GET, GEOTAGS_PATH + "/**").permitAll()
            .antMatchers("/api/**").authenticated()
            .anyRequest().permitAll()
            .and()
            .httpBasic()
            .realmName(SECURITY_REALM)
            .and()
            .csrf().disable().cors();
    }
}
授权服务器配置:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

private final TokenStore tokenStore;
private final JwtAccessTokenConverter accessTokenConverter;
private final AuthenticationManager authenticationManager;
private final DataSource dataSource;

@Autowired
public AuthorizationServerConfig(TokenStore tokenStore,
                                 JwtAccessTokenConverter accessTokenConverter,
                                 AuthenticationManager authenticationManager,
                                 @Qualifier("customDatasource") DataSource dataSource) {
    this.tokenStore = tokenStore;
    this.accessTokenConverter = accessTokenConverter;
    this.authenticationManager = authenticationManager;
    this.dataSource = dataSource;
}

@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
    configurer
            .jdbc(dataSource);
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    final TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
    enhancerChain.setTokenEnhancers(Collections.singletonList(accessTokenConverter));
    endpoints.tokenStore(tokenStore)
            .accessTokenConverter(accessTokenConverter)
            .tokenEnhancer(enhancerChain)
            .authenticationManager(authenticationManager);
  }
}
最后是SecurityConfig:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private static final String SIGNING_KEY = "Gz73RSOADKDFXzONqg3q";

private UserDetailsService customUserDetailsService;
private DataSource dataSource;

@Autowired
public void setCustomUserDetailsService(UserDetailsService customUserDetailsService) {
    this.customUserDetailsService = customUserDetailsService;
}

@Autowired
public void setDataSource(@Qualifier("customDatasource") DataSource dataSource) {
    this.dataSource = dataSource;
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}

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

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey(SIGNING_KEY);
    return converter;
}

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

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

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Collections.singletonList("*"));
    configuration.setAllowedMethods(Collections.singletonList("*"));
    configuration.setAllowedHeaders(Collections.singletonList("*"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);

    return source;
   }

}
如您所见,我使用的是CorsConfiguration源Bean,但当我们运行不同来源的javascript代码时:

fetch('http://localhost:8080/oauth/token', {
method: 'POST',
headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': `Basic ${window.btoa('eTaxiClientId:secret')}`
},
body: `username=${encodeURIComponent('Admin')}&password=${encodeURIComponent('pass')}&grant_type=password`
});
服务器响应,带有我在开头描述的消息

我还尝试使用我的WebMVCConfigureAdapter实现和重写的addCorsMappings方法,我尝试允许安装HttpMethod.OPTIONS,但浏览器始终发送与401代码匹配的选项请求

案例2(弹簧护套2)

在这个项目中,我尝试使用基本的Spring安全授权系统——没有OAuth2和JWT。我的配置是:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private final MyUserDetailsService userDetailsService;
private final DataSource dataSource;

public SecurityConfig(MyUserDetailsService userDetailsService,
                      @Qualifier("customDatasource") DataSource dataSource) {
    this.userDetailsService = userDetailsService;
    this.dataSource = dataSource;
}

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

    http
            .servletApi().and()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers("/api/1").hasAuthority("USER")
            .antMatchers("/api/2").hasAuthority("ADMIN")
            .antMatchers("/api/3").hasAuthority("GUEST")
            .and()
            .anonymous().principal("guest").authorities("GUEST")
            .and()
            .formLogin().permitAll()
            .successHandler(new CustomAuthenticationSuccessHandler())
            .failureHandler(new CustomAuthenticationFailureHandler())
            .and()
            .logout()
            .logoutSuccessUrl("/login")
            .invalidateHttpSession(true)
            .deleteCookies("JSESSIONID")
            .and()
            .exceptionHandling()
            .and()
            .rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository())
            .and()
            .headers()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .httpBasic()
            .and()
            .cors()
            .and()
            .csrf().disable();
 //                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

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

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

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
public PersistentTokenRepository tokenRepository() {
    JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
    jdbcTokenRepositoryImpl.setDataSource(dataSource);
    return jdbcTokenRepositoryImpl;
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedHeaders(Collections.singletonList("*"));
    configuration.setAllowedOrigins(Collections.singletonList("*"));
    configuration.setAllowedMethods(Collections.singletonList("*"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);

    return source;
}
}

在本例中,当我们在JavaScript应用程序中运行以下代码时:

  const body = `username=${encodeURIComponent('admin')}&password=${encodeURIComponent('pass')}`;

const hashedCredentials = btoa('admin:pass');

return axios.post(`${process.env.REACT_APP_API_URL}/login`, body, {
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        // test oauth credentials
        Authorization: `Basic ${hashedCredentials}`
    }
})
    .then(() => {
    localStorage.setItem('user', hashedCredentials);
})
.then(() => {
    const userCredentials = localStorage.getItem('user');

return axios.get(`${process.env.REACT_APP_API_URL}/api/2`, null, {
    headers: {
        Authorization: `Basic ${userCredentials}`
    }
});
}).then(res => console.log(res)).catch(err => console.log(err));
选项请求通过,我们有状态200响应,但正如您所看到的,我们试图将用户重定向到受保护的端点。但Spring Security并没有在屏幕上显示消息,而是重定向到登录页面

摘要

有人有这样的问题吗?有人看到我们做错了什么吗?为什么两个项目都有问题?更好(更安全)的用户身份验证方法

我希望我没有忘记描述一些事情,我期待着得到回应。干杯