我想基于spring-boot,spring-security和spring-oauth2设置一个简单的OAuth2提供程序。
我在一台实例计算机上运行了一切:对于OAuth2授权,用户被发送到/oauth/authorize
。大多数用户都没有登录,因此他们会被春季安全重定向到/login
,然后返回/oauth/authorize
以完成授权。
在默认配置中,spring-security在用户浏览器中使用session-id设置cookie,并将会话数据存储在内存中。
public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
[...]
为了在不丢失用户会话的情况下启用负载平衡和蓝绿色部署,(我认为)我必须执行以下步骤:
/login
重定向的重定向网址存储在其他位置
这种方法有意义吗?需要做哪些改变?
答案 0 :(得分:1)
这是分布式会话存储的典型问题。 首先,“会话”(会话ID和cookie)与“无国籍”相结合的概念是一种矛盾。
OAuth2应该是一个“无状态”委托授权框架提供您在生成访问代码之前在服务器端保留初始输入请求(包括重定向URL) 。
在接收凭据之前将这些详细信息泄露给Cookie可能会让您面临安全漏洞。您可以通过确保cookie HttpOnly (JS无法访问)和安全(仅通过httpS发布)来降低风险,但我不建议采用这种方法
关于您的另一点:Spring Security的remember-me功能仅用于提供对身份验证凭据的引用,而不是有关初始auth2请求的详细信息。此外,持久化选项(PersistentTokenBasedRememberMeServices)默认仅支持内存(单节点)和jdbc风格。
根据您的需求调整这些需要进行大量更改。可行,但需要付出很多努力。
根据我的经验,我想到了两种选择:
使用前端负载均衡器配置粘性会话(例如:haproxy,nginx,F5等...)。用户会话将绑定到提交凭据的节点。 这意味着如果该节点出现故障;用户必须重新进行身份验证才能创建新的访问令牌,但如果用于其他节点,则已经提供的访问令牌应该没有问题。
配置/实施透明的分布式网络会话存储。 一些分布式内存存储提供程序(例如:hazelcast)提供plugins,配置到应用程序服务器以使其对用户透明。这有一些额外的开销,但几乎没有额外的代码来满足您的要求。
答案 1 :(得分:0)
用户登录您的提供商后,您将生成一个授权代码,该代码将发送到客户端应用程序(通过重定向(回调)URL)。
稍后,客户端应用程序向您的服务器发出请求以获取访问令牌的请求。在此请求中,它提供了自动化代码。
此时,您需要能够将客户端应用程序发送的授权代码与您首先生成的授权代码进行比较。这是您需要共享内存的地方。
如果你看一下协议section-4.1的这一部分,你需要C点和D点之间的共享内存。
使用服务器之外的任何内容都无法实现这一点,因为这是您验证客户端应用程序是否已获得授权的重点。
在此过程的后期,访问和刷新令牌的情况类似。
对于登录步骤(A点和B点) - 在登录表单中包含重定向URL(和客户端状态 - 请参阅第4.1节)看起来很好。如果这是唯一使用会话的地方 - 你可以摆脱它。但是您仍然需要共享内存(共享数据库)来获取授权代码。