Authentication Spring安全-安全远程密码协议-SRP-身份验证提供程序

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(如

当问这个问题时,我正在寻找关于我自己的AuthenticationProvider实现的指导。我的意思是:

到目前为止,我已经了解到Spring安全性会询问AuthenticationProvider对象用户是否经过身份验证。目前我正在使用 DaoAuthenticationProvider,它处理由我自己的custome UserDetailService返回的用户名和密码。一切都很好! Spring支持很多不同的AuthenticationProvider,例如LDAP、Jdbc、DAO(如上所述)都有一个,我甚至可以找到一个Kerberos。但是,SRP没有身份验证提供程序,因此需要编写一个

我的问题如下:

当我们使用DaoAuthenticationProvider(即用户/密码验证)时,我们有一个html表单,其中输入用户名和密码,然后一个按钮负责提交这两个参数。购买的数据表通过某种传输通道传输到服务器,即只需单击一下,我们就可以在相同的http请求中发送所有数据,即验证所需的所有数据。可以在UsernamePasswordAuthenticationFilter中看到。这里的方法“attemptAuthentication”采用“HttpServletRequest请求”,其中包括用户名和密码。直到现在一切都很好

 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之前的一个步骤中调用,以验证数据库中是否存在用户名

我只对如何实现Srp身份验证有一个大致的想法,因此,如果这有意义,并且SRPAuthenticationEntryPoint是步骤a、b和c的正确位置,我希望得到一些评论。我觉得这不是个合适的地方

非常感谢您的反馈

问候,

蒂托

增补1(2014年11月21日)->对于“将负责客户端和服务器之间乒乓(对话)的代码放置在何处,即前3个步骤a、b和c”的问题,答案很可能是一个标准(我称之为协商)过滤器,它将承担该工作


现在我想重新表述这个问题,即在认证完成之前以及在接收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);