在提出这个问题时,我正在寻找实施我自己的AuthenticationProvider的指导。我的意思是:
到目前为止,我已经了解到,如果用户经过身份验证,Spring Security会询问AuthenticationProvider对象。目前我正在使用 DaoAuthenticationProvider处理由我自己的客户UserDetailService返回的用户名和密码。一切都很棒! Spring支持许多不同的AuthenticationProvider,例如有一个用于LDAP,Jdbc,DAO(如上所述),我甚至可以找到一个用于Kerberos。但是,SRP没有身份验证提供程序,因此需要编写一个。
我的问题如下:
当我们使用DaoAuthenticationProvider即用户/密码验证时,我们有一个html表单,其中输入用户名和密码,然后一个按钮负责提交这两个参数。买入的barameteres通过一些传输信道传输到服务器,即只需一次点击,我们就能够在同一个http请求中发送所有数据,即验证所需的全部数据。这可以在UsernamePasswordAuthenticationFilter中看到。这里的方法"尝试认证"需要" HttpServletRequest请求"其中包括用户名和密码。直到现在一切都好。
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
...
}
嗯,在简单的SRP中我们还有一个用户名和密码的表单,除了密码!!!必须!不能通过网络转移。为了实现这个限制,讨论"必须在客户端和服务器之间进行,即必须交换以下参数。
1)用户名(I),
2)一个名为" A"
3)一个名为" B"
4)一个名为" M1"
的值5)一个名为" M2"
的值好吧,让我们假设有一个名为" SrpAuthenticationProcessingFilter"的过滤器。如果新的身份验证协议更像是来自RFC 5054的对话,那么过滤器应该怎么样。
Client Server
Client Hello (I) -------->
Server Hello
Certificate*
Server Key Exchange (N, g, s, B)
<-------- Server Hello Done
Client Key Exchange (A) -------->
[Change cipher spec]
Finished -------->
[Change cipher spec]
<-------- Finished
Application Data <-------> Application Data
这里我们有一个需要
的客户端与用户名和密码身份验证相比,这些是7个步骤而不是1个步骤。其中3个需要在SrpAuthenticationProcessingFilter之前发生。现在我知道有可能将用户名与&#34;值A&#34;一起发送。从而缩短了步骤数,但我想严格遵循RFC。从来没有采取简单的方法吗?
问题实际上是我在哪里放置可以响应客户端和服务器之间的乒乓(对话)的代码,即上面提到的前3个步骤a,b和c。它应该将它们放在SrpEntryPoint对象中还是其他位置。 if else然后是在SpringSecurity的背景下?
我可以解决这个问题的一种方法是使用websockets,但我还想使该身份验证独立于任何第5-7层协议,如websockets,http,spdy等。这意味着第一个实现应该是简单的http请求/响应,然后是任何其他协议。
因此,目前实施SRP可能是正确的结构是:
SRPAuthenticationEntryPoint实现了org.springframework.security.web.AuthenticationEntryPoint - 这基本上说明了如果对受保护资源的请求进入,但用户尚未经过身份验证应该怎么做。在这里,我们可以在资源未经过身份验证的情况下进行重定向。也许这也是负责步骤a,b,c的地方,不确定这是否是正确的地方。请求指导和信息!!
SrpAuthenticationProcessingFilter扩展了GenericFilterBean。存在SrpAuthenticationProcessingFilter以进行部分验证,例如检查srp参数是否接收到服务器设置的srp参数的正确和corrspoding。这里重要的是要提到SrpAuthenticationProcessingFilter没有进行任何用户名验证,即需要在调用SrpAuthenticationProcessingFilter之前的一个步骤中发生,也许这是SrpEntryPoint或其他一些我不知道如何调用它的步骤。 SrpAuthenticationProcessingFilter有一个方法&#34; doFilter&#34;其中第二个结构正在创建,即SrpAuthenticationToken。
SrpAuthenticationToken扩展org.springframework.security.authentication.AbstractAuthenticationToken。我理解的那个标记与DAO对象类似,标记映射了sucessefull认证所需的所有字段。当部分验证的参数填充到SrpAuthenticationToken中时,SrpAuthenticationToken被传递给org.springframework.security.authentication.AuthenticationManager接口的authenticat方法,即类似的东西
myAuthentication = authenticationManager.authenticate(SrpAuthenticationToken);
根据Spring Security配置中配置的身份验证提供程序,在我们的情况下调用SrpAuthentication提供程序,即:
@Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(sRPAuthenticationProvider);
}
SRPAuthenticationProvider - 实现org.springframework.security.authentication.AuthenticationProvider。在这里,步骤d,e,f和g正在被验证和比较。如果出现错误,则抛出新的BadCredentialsException(&#34;无效的用户名/密码/ Verifiere&#34;)例外。
SrpSessionValidator - 这个只负责验证Srp会话的特定参数,并且可以从SrpAuthenticationProcessingFilter调用,也可以在SrpAuthenticationProcessingFilter之前的一个步骤中调用,以验证数据库中是否存在用户名。
我只知道如何实现Srp身份验证,因此我想要一些注释,如果这有意义,并且SRPAuthenticationEntryPoint是步骤a,b和c的正确位置。它对我来说不是一个合适的地方。
非常感谢任何反馈。
的问候,
铁托
Addition1(2014年11月21日) - &gt;作为问题的答案&#34;在哪里放置负责客户端和服务器之间的乒乓(对话)的代码,即前3个步骤a,b和c&#34;答案很可能是一个标准(我将称之为谈判)过滤器,它将承担这项工作。
现在我想重新解释这个问题,即在认证完成之前和接收到M1和M2消息之前,即步骤1 2和3.我在哪里放置该对象?即它应该是对象应该存在的地方,例如60秒,然后在没有收到M1和M2消息的情况下自动删除。我指的是&#34; SecurityContextHolder&#34;之前的一些对象。宾语。我只是不知道与spring security相关的对象/上下文的名称是什么,我也不知道这样的构造是否存在?
答案 0 :(得分:2)
我的方法是使用AJAX运行协议的第一部分,直到在客户端创建A
和M1
,然后将这些部分作为登录凭据发布到服务器并检查这些使用Spring Security。
要了解这是如何工作的,有junit-js测试在Thinbus上使用TestSRP6JavascriptClientSessionSHA256.js在javascript客户端对象和java服务器对象之间运行相互身份验证(请注意maven构建运行这个单元测试使用JDK javascript运行时):
// note the following exchange is written in javascript calling client js and invoking server java which is run by JUnit-JS using the JDK javascript runtime so it shows both sides of the full authentication in one unit test method
// normal login flow step1a client: browser starts with username and password given by user at the browser
client.step1(username,password);
// normal login flow step1b server: server starts with username from browser plus salt and verifier saved to database on user registration.
var B = server.step1(username, salt, v);
// normal login flow step2a client: server sends users salt from user registration and the server ephemeral number
var credentials = client.step2(salt, B);
// normal login flow step2b server: client sends its client ephemeral number and proof of a shared session key derived from both ephermal numbers and the password
var M2 = server.step2(credentials.A, credentials.M1);
// normal login flow step3 client: client verifies that the server shows proof of the shared session key which demonstrates that it knows actual verifier
client.step3(M2);
显然,javascript客户端仅以username
和password
开头。服务器使用username
解析salt
并生成随机B
。客户端从服务器获得salt
和B
,并生成其随机A
和M1
密码证明。以step2
为参数的服务器M1
是检查用户密码证明的服务器,如果证据不正确,它将抛出异常。然后,服务器发送M2
,这是服务器证明它具有用户验证者v
,这样做是为了防止虚假服务器欺骗真实服务器。
有一个浏览器的演示使用Thinbus在thinbus-srp-js-demo上通过AJAX对Java服务器进行SRP。你可以使用AJAX方法重新使用JAX RS(例如Spring MVC AJAX)来执行在客户端创建A
+ M1
的第一步,然后使用登录将它们发布到Spring Security通过在服务器对象上运行A
来形成帖子并让Spring Security验证M1
+ step2
,如junit-js测试中所示。然后你的AuthenticationManager
可以从用户名密钥的并发映射中解析AJAX创建的服务器对象。
如果您将HTTPS用于服务器,我会考虑将服务器证明M2
视为可选。如果您不使用HTTPS,那么服务器欺骗意味着他们可以为用户提供一个发送密码并忽略错误M2的页面;所以M2证明在网页的上下文中没有提供安全性。使用类似手机间隙之类的东西将html / js打包到本机应用程序中的移动应用程序将受益于M2检查;用户登录后可以将其添加到页面中以供受信任的代码检查。
答案 1 :(得分:2)
https://bitbucket.org/simon_massey/thinbus-srp-spring-demo
有一个Spring安全SRP实施自述页面上写着:
整合的一个显着特点是没有变化 除了以外的标准spring安全认证路径 配置自定义
SrpAuthenticationProvider
。
它还说:
Spring Security不会将用户HTTPSession暴露给 的AuthenticationProvider。因此,演示代码使用具有超时的Guava缓存 在短暂的时间内保持SRP6JavascriptServerSession 登录交换。从Thinbus 1.2.1开始,会话是可序列化的 大型无国籍网站的替代方法是持有 数据库中的SRP6JavascriptServerSession对象而不是 内存缓存。