Web应用程序中的身份验证

原文地址:https://docs.spring.io/spring-security/site/docs/4.2.6.RELEASE/reference/htmlsingle/#authorization

一个典型的Web应用程序的身份验证过程:

  1. 您访问主页,然后点击链接。
  2. 请求发送到服务器,并且服务器确定您已请求受保护的资源。
  3. 由于您目前没有通过身份验证,因此服务器会发回一个响应,指出您必须进行身份验证。响应可能是HTTP响应代码,也可能是重定向到特定网页。
  4. 根据身份验证机制,您的浏览器将重定向到特定网页,以便填写表单,或者浏览器以某种方式检索您的身份(通过BASIC身份验证对话框,Cookie,X.509证书等) )。
  5. 浏览器会发回一个响应给服务器。这将是一个HTTP POST,其中包含您填写的表单的内容,或者包含您的验证细节的HTTP标头。
  6. 接下来,服务器将决定提交的凭证是否有效。如果它们有效,下一步就会发生。如果它们无效,通常你的浏览器会被要求重试(所以你回到上面的第二步)。
  7. 您重做的原始请求将导致身份验证过程。希望您已通过足够的授权机构进行身份验证,以访问受保护的资源。如果您有足够的访问权限,请求将会成功。否则,您将收到一个HTTP错误代码403,意思是“禁止”。

Spring Security具有不同的类,负责上述大多数步骤。主要参与者(在使用它们的顺序)是ExceptionTranslationFilter,一个AuthenticationEntryPoint和“验证机制”,它负责调用AuthenticationManager

1 ExceptionTranslationFilter

ExceptionTranslationFilter是一个Spring Security过滤器,负责检测抛出的任何Spring Security异常。这种例外情况通常会由AbstractSecurityInterceptor授权服务的主要提供者 - 一个引发我们将AbstractSecurityInterceptor在下一节讨论,但现在我们只需要知道它会产生Java异常,并且对HTTP没有任何认识,或者如何去认证一个主体。相反,ExceptionTranslationFilter该服务提供此服务,具体负责返回错误代码403(如果委托人已经过身份验证,因此根本没有足够的访问权限 - 按照上面的第7步),或者启动一个AuthenticationEntryPoint(如果委托人未经过身份验证,因此我们需要开始第三步)。

2 AuthenticationEntryPoint

AuthenticationEntryPoint负责第三步在上面的列表中。正如你可以想象的那样,每个Web应用程序都会有一个默认的身份验证策略(当然,这可以像Spring Security中的其他任何东西一样配置,但现在让我们保持简单)。每个主要认证系统都有其自己的AuthenticationEntryPoint实施,通常执行步骤3中描述的操作之一。

3认证机制

一旦您的浏览器提交了您的身份验证凭证(无论是作为HTTP表单发布还是HTTP标头),服务器上都需要有一些“收集”这些身份验证信息的东西。到目前为止,我们正在上面的列表中的第六步。在Spring Security中,我们为从用户代理(通常是Web浏览器)收集验证信息的功能提供了一个特殊的名称,称之为“验证机制”。示例是基于表单的登录和基本身份验证。一旦从用户代理收集了认证详细信息,Authentication就会构建一个“请求”对象并呈现给该用户代理AuthenticationManager

在认证机制接收到完全填充的Authentication对象之后,它将认为请求有效,将其Authentication放入SecurityContextHolder并导致原始请求被重试(上面的步骤7)。另一方面,如果AuthenticationManager拒绝请求,认证机制将要求用户代理重试(上面的第二步)。

4在请求之间存储SecurityContext

根据应用程序的类型,可能需要制定一个策略来存储用户操作之间的安全上下文。在典型的Web应用程序中,用户登录一次,随后通过其会话ID进行标识。服务器缓存持续时间会话的主要信息。在Spring Security中,存储SecurityContext请求之间的责任归属于SecurityContextPersistenceFilter默认情况下,将上下文存储为HttpSessionHTTP请求之间属性。SecurityContextHolder为每个请求恢复上下文,并且关键地清除SecurityContextHolder请求完成的时间。HttpSession出于安全目的,您不应直接与之交互这样做根本没有理由 - 总是使用它SecurityContextHolder

许多其他类型的应用程序(例如,无状态的RESTful Web服务)不使用HTTP会话,并将在每个请求中重新进行身份验证。但是,SecurityContextPersistenceFilter包含在链中以确保SecurityContextHolder在每次请求后清除它仍然很重要

[注意]

在单个会话中接收并发请求的应用程序中,同一个SecurityContext实例将在线程之间共享。即使ThreadLocal正在使用a,它也是从HttpSession每个线程检索的同一个实例如果您想临时更改线程正在运行的上下文,这会产生影响。如果您只是使用SecurityContextHolder.getContext()并调用setAuthentication(anAuthentication)返回的上下文对象,则Authentication对象将在共享相同实例的所有并发线程中更改SecurityContext您可以自定义行为SecurityContextPersistenceFilter以创建一个全新的行为SecurityContext对于每个请求,阻止一个线程中的更改影响另一个线程。或者,您可以在临时更改上下文的位置创建新实例。该方法SecurityContextHolder.createEmptyContext()总是返回一个新的上下文实例。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值