Mar*_*ark 5 java spring-security spring-security-oauth2
我想知道是否可以将 Spring Security 配置为在 OAuth 登录过程中使用外部托管的登录页面。没关系,这不是一个好主意,并且违背了 OAuth 的目的之一(将登录/凭据/身份验证问题与客户端和资源服务器分开)。
我有以下设置:
@EnableAuthorizationServer)我寻求的OAuth流程如下:
我可以配置 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 会话设置才能解决此问题?
问题根本不在于 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 请求一起发送。