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

Tit*_*ito 5 authentication authorization spring-security srp-protocol

在提出这个问题时,我正在寻找实施我自己的AuthenticationProvider的指导.我的意思是:

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

我的问题如下:

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

 public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        ...
        }
Run Code Online (Sandbox Code Playgroud)

好吧,在简单的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
Run Code Online (Sandbox Code Playgroud)

在这里,我们有一个需要的客户

  • a)首先发送他的用户名(I)
  • b)然后服务器需要用值B进行响应(在这种情况下,N,g,s不是必需的)
  • c)客户发送它的"价值A"
  • d)客户端使用来自服务器的值B并基于该值计算密钥.
  • e)服务器也根据值A计算密钥.
  • f)客户端将值M1发送到服务器.
  • g)服务器获取M1值并基于具有M1值作为参数的公式,他能够验证密钥是否匹配,如果所购买方的计算密钥匹配则用户被认证,并且产品即共享密钥可以进一步用于其他处理.

与用户名和密码身份验证相反,这些是7个步骤而不是1个步骤.其中3个需要在SrpAuthenticationProcessingFilter之前发生.现在我知道有可能将用户名与"值A"一起发送,从而缩短了步骤数,但我想严格遵循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有一个方法"doFilter",其中第二个结构是创建的,即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);
}
Run Code Online (Sandbox Code Playgroud)
  • SRPAuthenticationProvider - 实现org.springframework.security.authentication.AuthenticationProvider.在这里,步骤d,e,f和g正在被验证和比较.如果出现错误,则抛出新的BadCredentialsException("Invalid username/password/Verifiere")异常.

  • SrpSessionValidator - 这个仅负责验证Srp会话的特定参数,并且将从SrpAuthenticationProcessingFilter以及SrpAuthenticationProcessingFilter之前的一个步骤中调用,以便验证数据库中是否存在用户名.

我只是一般的想法如何实现Srp身份验证,因此我想要一些评论,如果这是有意义的,如果SRPAuthenticationEntryPoint是步骤a,b和c的正确位置.它对我来说不是一个合适的地方.

任何反馈都非常感谢.

问候,

铁托

Addition1(2014年11月21日) - >作为问题的答案"在哪里放置负责客户端和服务器之间乒乓(对话)的代码,即前3个步骤a,b和c"的答案这很可能是一个标准(我称之为协商)过滤器,它将承担这项工作.

现在我想重新解释这个问题,即在认证完成之前和接收到M1和M2消息之前,即步骤1 2和3.我在哪里放置该对象?即,它应该是对象应该存在的地方,例如60秒,然后在没有收到M1和M2消息的情况下自动删除.我指的是"SecurityContextHolder"对象之前的一些对象.我只是不知道与spring security相关的对象/上下文的名称是什么,我也不知道这样的构造是否存在?

sim*_*905 2

我的方法是使用 AJAX 运行协议的第一部分,直到创建AM1在客户端,然后将这些内容作为登录凭据发布到服务器,并使用 Spring Security 检查这些内容。

要了解其工作原理,有一个junit-js测试,它使用ThinbusTestSRP6JavascriptClientSessionSHA256.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);
Run Code Online (Sandbox Code Playgroud)

显然,javascript 客户端仅以username和开头password。服务器使用username来解析salt并生成一个随机的B. 客户端从服务器获得saltB生成其随机数A,这M1就是密码证明。step2作为参数的服务器M1是检查用户密码证明的服务器,如果证明不正确,它将抛出异常。然后,服务器发送M2服务器证明,证明它具有用户验证器v,这样做是为了防止假服务器欺骗真实服务器。

在Thinbus-srp-js-demo上有一个浏览器使用Thinbus通过 AJAX 对 Java 服务器执行 SRP 的演示。您可以通过 AJAX 方法(例如 Spring MVC AJAX)重新使用 JAX RS 来执行在客户端创建+的第一步,然后使用登录表单发布将这些步骤发布到 Spring Security,并通过运行Spring Security 验证+在服务器对象上,如 junit-js 测试所示。然后,您可以从由用户名键入的并发映射中解析 A​​JAX 创建的服务器对象。AM1AM1step2AuthenticationManager

一个小注意事项是,M2如果您使用 HTTPS 连接服务器,我会考虑将检查服务器证明作为可选操作。如果您不使用 HTTPS,那么服务器欺骗意味着他们可以向用户提供一个发送密码并忽略错误 M2 的页面;因此 M2 证明不提供网页上下文中的安全性。使用诸如电话间隙之类的东西将 html/js 打包到本机应用程序中的移动应用程序将受益于 M2 检查;可以在用户登录后添加到页面中,以供可信代码检查。