Authentication Spring安全-安全远程密码协议-SRP-身份验证提供程序
当问这个问题时,我正在寻找关于我自己的AuthenticationProvider实现的指导。我的意思是: 到目前为止,我已经了解到Spring安全性会询问AuthenticationProvider对象用户是否经过身份验证。目前我正在使用 DaoAuthenticationProvider,它处理由我自己的custome UserDetailService返回的用户名和密码。一切都很好! Spring支持很多不同的AuthenticationProvider,例如LDAP、Jdbc、DAO(如上所述)都有一个,我甚至可以找到一个Kerberos。但是,SRP没有身份验证提供程序,因此需要编写一个 我的问题如下: 当我们使用DaoAuthenticationProvider(即用户/密码验证)时,我们有一个html表单,其中输入用户名和密码,然后一个按钮负责提交这两个参数。购买的数据表通过某种传输通道传输到服务器,即只需单击一下,我们就可以在相同的http请求中发送所有数据,即验证所需的所有数据。可以在UsernamePasswordAuthenticationFilter中看到。这里的方法“attemptAuthentication”采用“HttpServletRequest请求”,其中包括用户名和密码。直到现在一切都很好Authentication Spring安全-安全远程密码协议-SRP-身份验证提供程序,authentication,spring-security,authorization,srp-protocol,Authentication,Spring Security,Authorization,Srp Protocol,当问这个问题时,我正在寻找关于我自己的AuthenticationProvider实现的指导。我的意思是: 到目前为止,我已经了解到Spring安全性会询问AuthenticationProvider对象用户是否经过身份验证。目前我正在使用 DaoAuthenticationProvider,它处理由我自己的custome UserDetailService返回的用户名和密码。一切都很好! Spring支持很多不同的AuthenticationProvider,例如LDAP、Jdbc、DAO(如
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
...
}
好的,在简单的in-SRP中,我们还有一个表单,除了密码之外,还有用户名和密码!!!必须不能通过网络传输。为了实现该约束,必须在客户端和服务器之间进行“讨论”,即必须交换以下参数
1) 用户名(I)
2) 一个称为“a”的值
3) 一个称为“B”的值
4) 一个称为“M1”的值
5) 一个称为“M2”的值
好的,让我们假设有一个名为“SrpAuthenticationProcessingFilter”的过滤器,如果新的身份验证协议更像是一个对话,那么这个过滤器应该是什么样子的,我的意思是来自RFC554
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
- SRPAuthenticationProvider-实现org.springframework.security.authentication.AuthenticationProvider。在这里,正在验证和比较步骤d、e、f和g。如果发生错误,则抛出新的BadCredentialsException(“无效用户名/密码/验证”)异常
- SrpSessionValidator-此程序仅负责验证Srp会话的特定参数,并将从SrpAuthenticationProcessingFilter调用,以及在SrpAuthenticationProcessingFilter之前的一个步骤中调用,以验证数据库中是否存在用户名
现在我想重新表述这个问题,即在认证完成之前以及在接收M1和M2消息之前,即步骤1、2和3。我应该把那个东西放在哪里?也就是说,它应该是一个对象应该居住的地方,例如60秒,然后在没有收到M1和M2消息的情况下自动删除。我指的是“SecurityContextHolder”对象之前的某个对象。我只是不知道与spring安全性相关的对象/上下文的名称,也不知道是否存在这样的构造 我的方法是使用AJAX运行协议的第一部分,直到在客户端创建
A
和M1
,然后将它们作为登录凭据发布到服务器,并使用Spring安全性检查它们
要了解这是如何工作的,有一个测试使用over at在javascript客户端对象和java服务器对象之间运行相互身份验证(注意maven构建使用JDK javascript运行时运行此单元测试):
显然,javascript客户端只以用户名
和密码
开始。服务器使用username
解析salt
,并生成一个随机B
。客户端从服务器获得salt
和B
,并生成其随机A
和M1
,这是密码证明。以M1
为参数的服务器step2
是检查用户密码证明的服务器,如果证明不正确,它将抛出异常。然后,服务器发送M2
,这是服务器证明它有用户验证程序v
,这样做是为了防止假服务器欺骗真实服务器
这里有一个浏览器使用overat通过AJAX对Java服务器执行SRP的演示。您可以将JAX-RS与AJAX方法结合使用(例如springmvcajax)要在客户端执行创建A
+M1
之前的第一步,请使用登录表单post将这些步骤发布到Spring Security,并通过在服务器对象上运行step2
来验证A
+M1
,如junit js测试所示。然后,您的AuthenticationManager
可以从由用户名键入的并发映射解析由AJAX创建的服务器对象
一个小注意是,如果您使用HTTPS到服务器,我会考虑检查服务器证明<代码> M2<代码>是否为可选的。如果您不使用HTTPS,那么服务器欺骗意味着他们可以向用户提供
@Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(sRPAuthenticationProvider);
}
// 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);