当前位置: 首页 > 知识库问答 >
问题:

Spring Security-安全远程密码协议- SRP -认证提供者

尹昂雄
2023-03-14

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

到目前为止,我了解到Spring Security询问AuthenticationProvider对象用户是否被认证。目前我正在使用DaoAuthenticationProvider来处理我自己的客户UserDetailService返回的用户名和密码。一切都很好!Spring支持许多不同的认证提供者,例如LDAP、Jdbc、DAO(如上所述)都有一个,我甚至能找到一个用于Kerberos的。然而,SRP没有身份验证提供程序,因此需要编写一个。

我的问题如下:

当我们使用D安保认证提供者,即用户/密码认证时,我们有一个HTML表单,在其中输入用户名和密码,然后一个按钮负责提交这两个参数。购买的参数通过一些传输通道传输到服务器,即只需单击一下,我们就可以发送同一超文本传输协议请求中的所有数据,即身份验证所需的所有数据。这可以在UsernamePassword身份认证过滤器中看到。这里的方法“尝试认证”采用“HttpServlet请求”,其中包括用户名和密码。到目前为止一切都很好。

 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

在这里,我们有一个需要

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

与用户名和密码认证相比,这是7个步骤,而不是一个步骤。其中3个需要在SrpAuthenticationProcessingFilter之前发生。现在我意识到有可能将用户名和“值A”一起发送,从而缩短步骤数,但我希望严格遵循RFC。永远不要走捷径,对吗?

真正的问题是,我应该把负责客户端和服务器之间乒乓(对话)的代码放在哪里,即上面提到的前3个步骤a、b和c。它应该把它们放在SrpEntry Point对象中,还是放在其他地方。如果还有的话,那就在SpringSecurity的上下文中?

我可以解决这个问题的一种方法是使用websockets,但我也希望使身份验证独立于任何5-7层协议,如html" target="_blank">websocket、http、spdy等。这意味着第一个实现应该是通过简单的http请求/响应,然后使用任何其他协议。

因此,当前实施SRP的正确结构是:

>

  • SRPAuthenticationEntryPoint 实现了 org.springframework.security.web.AuthenticationEntryPoint - 这基本上说明了如果对受保护资源的请求进入,但用户尚未通过身份验证,应该怎么做。在这里,我们可以在资源尚未经过身份验证的情况下放置重定向。也许这也是负责步骤a,b,c的地方,不确定这是否是正确的地方。请求指导和信息!!

    SrpAuthenticationProcessingFilter扩展了GenericFilterBean。SrpAuthenticationProcessingFilter的存在是为了进行部分验证,例如检查srp参数是否接收到了与服务器设置的srp参数相对应的正确数据。在这里,重要的是要提到SrpAuthenticationProcessingFilter不做任何用户名验证,也就是说,这需要在调用SrpAuthenticationProcessingFilter之前的一个步骤中发生,也许这是SrpEntryPoint或其他我还不知道如何调用它的步骤。SrpAuthenticationProcessingFilter有一个方法“doFilter ”,其中创建了第二个结构,即SrpAuthenticationToken。

    SrpAuthenticationToken extend org . spring framework . security . authentication . abstractauthenticationtoken .这个令牌在我理解中有点类似于DAO对象,这个令牌映射了成功完全身份验证所需的所有字段。当部分验证的参数被填充到SrpAuthenticationToken中时,SrpAuthenticationToken被传递到org . spring framework . security . authentication . authentication manager接口的authenticat方法,即类似这样的内容

    myAuthentication=authenticationManager.authenticate(SrpAuthenticationToken);

    根据在Spring Security配置中配置了哪个Authentication Provider,则在我们的情况下调用SrpAuthentification Provider,即:

    @Autowired
    public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth
              .authenticationProvider(sRPAuthenticationProvider);
    }
    

    >

  • SRPAuthenticationProvider-实现org.springframework.security.authentication.AuthenticationProvider。在这里,步骤d、e、f和g正在被验证和比较。如果发生错误,则抛出新的BadCredentialsException(“用户名/密码/验证无效”)异常。

    SrpSessionValidator-这个只负责验证Srp会话的特定参数,并将从SrpAuth

    我只对如何实现Srp身份验证有一个大致的概念,因此,如果这有意义,如果SRPAuthenticationEntryPoint是步骤a、b和c的正确位置,我想提出一些意见。

    任何反馈都非常感谢。

    问候

    铁托

    增补1(2014年11月21日)-

    现在,我想重新表述这个问题,即在身份验证完成之前以及在接收到M1和M2消息之前,即步骤1、2和3。我应该将该对象放在哪里?一、 e.它应该是一个对象应该居住的地方,例如60秒,然后在没有接收到M1和M2消息的情况下自动删除。我是指“SecurityContextHolder”对象之前的某个对象。我只是不知道与Spring Security相关的对象/上下文的名称是什么,也不知道是否存在这样的结构?

  • 共有2个答案

    金伟
    2023-03-14

    在 https://bitbucket.org/simon_massey/thinbus-srp-spring-demo 有一个Spring安全SRP暗示

    自述文件页面说:

    集成的一个显著特点是,除了配置自定义SrpAuthenticationProvider之外,对标准Spring Security身份验证路径没有任何更改。

    它还说:

    Spring Security不会向AuthenticationProvider公开用户HTTPSession。因此,演示代码使用一个Guava缓存,在登录交换的短暂时间内保持SRP6JavascriptServerSession。从Thinbus 1.2.1开始,会话是可序列化的,因此大型无状态网站的另一种方法是将SRP6JavascriptServerSession对象保存在数据库中,而不是存储在内存缓存中。

    余信然
    2023-03-14

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

    要了解它是如何工作的,有一个junit-js测试,它在TestSRP6JavascriptClientSessionSHA256中使用Thinbus在javascript客户端对象和java服务器对象之间运行相互身份验证.js(请注意,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客户端仅从< code >用户名和< code >密码开始。服务器使用< code >用户名来解析< code>salt并生成一个随机的< code>B。客户端从服务器获得< code>salt和< code>B,并生成其随机< code>A和< code>M1,后者是密码证明。以< code>M1为参数的服务器< code>step2是检查用户密码证明的服务器,如果证明是错误的,它将抛出异常。然后,服务器发送< code>M2,这是服务器证明它具有用户验证符< code>v,这样做是为了防止假冒服务器欺骗真实服务器。

    在thinbus-srp-js-demo上有一个浏览器使用Thinbus通过AJAX对Java服务器进行SRP的演示。您可以重用JAX RS with AJAX方法(例如Spring MVC AJAX)来执行第一步,直到在客户端创建< code>A M1,然后使用登录表单post将这些内容发布到Spring Security,并让Spring Security通过在服务器对象上运行< code>step2来验证< code>A,如junit-js测试所示。然后,您的< code > AuthenticationManager 可以从以username为关键字的并发映射中解析AJAX创建的服务器对象。

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

     类似资料:
    • 我正在尝试使用pact来验证spring boot微服务。我已经从consumer生成了pact文件,并在provider端使用pact Broker验证了它。 我有另一个用例,在根据实际的服务响应验证pact文件之前,我需要执行一些代码。我读过关于状态改变URL和状态改变与闭包来实现它,但没有得到一个如何实现这一点的例子。有人能帮忙吗? 如果这个客户不存在,那么我将需要通过读取pact文件中的更

    • 我为Jetty 9和Kafka使用ssl密钥库。我需要提供密钥库和密钥密码来访问密钥库和私钥。但是,我不想在配置文件中以明文形式提供这些密码。还有哪些其他选项可以安全地提供/加密密码?每种方法的优缺点是什么?

    • gRPC 被设计成可以利用插件的形式支持多种授权机制。本文档对多种支持的授权机制提供了一个概览,并且用例子来论述对应API,最后就其扩展性作了讨论。 马上将会推出更多文档和例子。 支持的授权机制 SSL/TLS gRP 集成 SSL/TLS 并对服务端授权所使用的 SSL/TLS 进行了改良,对客户端和服务端交换的所有数据进行了加密。对客户端来讲提供了可选的机制提供凭证来获得共同的授权。 OAut

    • 例子 # getpass_defaults.py import getpass try: p = getpass.getpass() except Exception as err: print('ERROR:', err) else: print('You entered:', p) # getpass_prompt.py import getpass p = ge

    • Cookies 和 secure cookies 你可以使用 set_cookie 方法在用户的浏览器中设置 cookies: class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_cookie("mycookie"): self.set_cooki

    • 包括平台认证体系架构和安全告警等内容。 认证体系 认证体系主要包括认证源、域、项目、组、用户、权限、角色等信息。 安全告警 安全告警即实时监测系统中的安全告警事件,如异常登录等,当发现安全问题后,将会及时通知管理员用户进行处理等。