【问题标题】:OAuth2 with Google - CORS Error (Angular + Spring boot) [duplicate]带有 Google 的 OAuth2 - CORS 错误(Angular + Spring boot)[重复]
【发布时间】:2020-02-07 00:18:13
【问题描述】:

我遇到了 CORS 错误的问题。我确实请求了 Google oAuth2,但我收到了一个 CORS 错误: 我想获得谷歌身份验证并生成 JWT 令牌。当我在不使用客户端的情况下执行此操作时,一切都很好。当我发送角度请求时,这是 CORS 的问题。我允许所有类型的 CORS。为什么会出现此错误?

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=1020159669873-d9r35ssmnejud852bam87d8gqtcj5qf1.apps.googleusercontent.com&scope=openid%20profile%20email&state=8nizHP1X2z9sA8m0vqM4Lzd6VT24R15eSw5flteTywM%3D&redirect_uri=http://localhost:8080/oauth2/callback/google' (redirected from 'http://localhost:8080/oauth2/authorization/google')
from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=1020159669873-d9r35ssmnejud852bam87d8gqtcj5qf1.apps.googleusercontent.com&scope=openid%20profile%20email&state=8nizHP1X2z9sA8m0vqM4Lzd6VT24R15eSw5flteTywM%3D&redirect_uri=http://localhost:8080/oauth2/callback/google with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.

我的 Angular 请求:

 googleLogin(): Observable<LoginResponse> {
    return this.http.get<LoginResponse>
    (environment.baseUrl + '/oauth2/authorization/google')
      .pipe(tap(response => {
        localStorage.setItem('access_token', response.accessToken);
      }));
  }

//...

public onGoogleLogin(): void {
   this.authService.googleLogin().subscribe();
 }

//...

CORS 配置:

 @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
                .maxAge(MAX_AGE_SECS);
    }

安全配置:

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                    .and()
                .csrf()
                    .disable()
                .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler)
                    .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                .authorizeRequests()
                    .antMatchers("/",
                "/favicon.ico",
                "/**/*.png",
                "/**/*.gif",
                "/**/*.svg",
                "/**/*.jpg",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js")
                        .permitAll()
                .antMatchers("/api/v1/oauth0/**")
                        .permitAll()
                .antMatchers("/api/v1/oauth2/**")
                    .permitAll()
                .anyRequest()
                    .authenticated()
                    .and()
                // włączenie obslugi oauth2
                .oauth2Login()
                .successHandler(this.successHandler)
                .redirectionEndpoint()
                    .baseUri("/oauth2/callback/*")
                    .and()
                .userInfoEndpoint()
                    .oidcUserService(customOidcUserService);
        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

成功处理程序:

@Autowired
    private UserRepository userRepository;

    @Autowired
    private JwtTokenProvider tokenProvider;

    private final static String URL = "http://localhost:8080/api/v1/oauth2/authenticate";

    @Override
    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {

        if (response.isCommitted()) {
            return; }

        DefaultOidcUser oidcUser = (DefaultOidcUser) authentication.getPrincipal();
        System.out.println(oidcUser);
        Map attributes = oidcUser.getAttributes();
        String email = attributes.get("email").toString();
        User user = userRepository.findByEmail(email).orElseThrow(
                () -> new ResourceNotFoundException("User", "email", email)
        );
        String token = tokenProvider.generateToken(user);
        String redirectionUrl = UriComponentsBuilder.fromUriString(URL).queryParam("token", token)
                .build().toUriString();
        getRedirectStrategy().sendRedirect(request, response, redirectionUrl);
    }
}

控制器:

@RestController
@RequestMapping("/api/v1/oauth2")
public class OAuth2Controller {

    @GetMapping("/authenticate")
    public ResponseEntity<?> authenticateUser(@RequestParam String token) {
        return ResponseEntity.ok(new JwtAuthenticationResponse(token));
    }
}

【问题讨论】:

标签: java angular spring-security spring-security-oauth2


【解决方案1】:

您无法在此示例中获取令牌,因为您需要进行实际重定向。有几种方法可以规避此要求,详细信息请参见 RFC https://www.rfc-editor.org/rfc/rfc6749#section-1.2

  1. 在弹出窗口中启动授权流程,并通过浏览器中提供的postMessage() API 将服务器收到的令牌从弹出窗口传回 web 应用程序。
  2. 保存状态,无论它是什么,重定向到服务器,该服务器将启动授权流程,在交换令牌以获得授权后,使用令牌作为查询字符串参数重定向回 webapp。然后使用它并恢复状态。

【讨论】:

  • 我会寻找一些示例代码并尝试这样做。感谢您的时间。如果我成功了,我会通知你
猜你喜欢
  • 2020-09-08
  • 2019-07-21
  • 2021-11-09
  • 2019-05-05
  • 2017-05-13
  • 2019-02-14
  • 2018-03-06
  • 2021-03-01
相关资源
最近更新 更多