使用外部登录页面的 Spring Security OAuth2 登录

Mar*_*ark 5 java spring-security spring-security-oauth2

我想知道是否可以将 Spring Security 配置为在 OAuth 登录过程中使用外部托管的登录页面。没关系,这不是一个好主意,并且违背了 OAuth 的目的之一(将登录/凭据/身份验证问题与客户端和资源服务器分开)。

我有以下设置:

  • 客户端 SPA 应用程序,我要使用的登录页面位于其中
  • OAuth Auth 服务器(使用 Spring Security OAuth / @EnableAuthorizationServer
  • 一台或多台 OAuth 资源服务器

我寻求的OAuth流程如下:

  • 用户尝试访问 SPA 中的安全路由
  • 客户端将用户重定向到OAuth服务器的授权页面(参数包括状态、随机数等)
  • OAuth 服务器未检测到令牌并重定向到 SPA 的登录页面
  • 用户登录;发布到登录 url(登录 url 位于 OAuth 服务器上;需要 CORS 配置以允许从 SPA 到 OAuth 服务器的跨源发布)
  • 登陆成功; Spring使用最初存在的参数重定向到最初请求的授权页面
  • 授权重定向到令牌;用户获得令牌;SPA 检测到用户现在拥有令牌并允许访问安全路由

我可以配置 Spring Security 来指定绝对 URL,以便重定向到 SPA 的登录页面:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors()
        .and()
        ... config ...
        .and()
        .formLogin()
        .loginPage("http://angular-spa-app/login") 
        .loginProcessingUrl("/login")
        .permitAll();
}
Run Code Online (Sandbox Code Playgroud)

当我完成此流程时,我看到第一个请求发送到oauth/authorize?state=...&nonce=...&etc...,然后重定向到http://angular-spa-app/login。但是当我登录时,Spring 无法检测到它应该重定向回oauth/authorize会话中保存的 url。

进一步深入研究,我发现当oauth/authorize发出第一个请求时,带有参数的完整 url 会保存在会话中(HttpSessionRequestCache.saveRequest(...).

当登录表单提交并且身份验证成功时,Spring 尝试检索保存的请求,以便获取要作为 302 Location 标头发送的重定向 url。但是当它执行此操作时,会话为空,因此 Spring 无法检索任何已保存的请求。为什么是这样?我是否需要修改 Spring 会话设置才能解决此问题?

Mar*_*ark 2

问题根本不在于 Spring Security;而是在于 Spring Security。它是与 Angular SPA 一起使用的。当从 Angular 应用程序将跨域 POST 返回到 /login 时,我需要发送 JSESSION_ID cookie。

为此,我创建了一个HttpInterceptor如此处所述):

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      withCredentials: true
    });
    return next.handle(request);
  }
}
Run Code Online (Sandbox Code Playgroud)

钻头withCredentials: true是重要的部分;这指示浏览器将 cookie 与 XHR 请求一起发送。

  • 感谢您花时间发布解决方案,因为我遇到了类似的问题。oAuth 已经够繁琐的了,但是添加外部登录页面肯定不会让它变得更简单。干杯! (2认同)