说道说道SpringSecurity身份认证

Spring Security可以运行在不同的身份认证环境中,当我们推荐用户使用Spring Security进行身份认证但并不推荐集成到容器管理的身份认证中时,但当你集成到自己的身份认证系统时,它依然是支持的。

1. Spring Security中的身份认证是什么?

现在让我们考虑一下每个人都熟悉的标准身份认证场景:

(1)用户打算使用用户名和密码登陆系统

(2)系统验证用户名和密码合法

(3)得到用户信息的上下文(角色等信息)

(4)为用户建立一个安全上下文

(5)用户接下来可能执行一些权限访问机制下的受保护的操作,检查与当前安全上下文有关的必须的权限

上面前三步是身份认证的过程,接下来看看身份认证的详细过程:

(1)用户名和密码获得之后组合成 UsernamePasswordAuthenticationToken 的实例(前文讨论过的Authentication接口的实例)

(2)将该令牌传递给 AuthenticationManager 实例进行验证

(3)验证成功后,AuthenticationManager 会返回填充好的 Authentication 实例

(4)通过调用 SecurityContextHolder.getContext().setAuthentication(...) 建立安全上下文的实例,传递到返回的身份认证对象上

下面是进行身份认证的代码片段:

import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class AuthenticationExample {

  private static AuthenticationManager am = new SampleAuthenticationManager();

  public static void main(String[] args) throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    while(true) {
      System.out.println("Please enter your username:");
      String name = in.readLine();
      System.out.println("Please enter your password:");
      String password = in.readLine();
      try {
        Authentication request = new UsernamePasswordAuthenticationToken(name, password);
        Authentication result = am.authenticate(request);
        SecurityContextHolder.getContext().setAuthentication(result);
        break;
      } catch(AuthenticationException e) {
        System.out.println("Authentication failed: " + e.getMessage());
      }
    }
    System.out.println("Successfully authenticated. Security context contains: " +
              SecurityContextHolder.getContext().getAuthentication());
  }
}

class SampleAuthenticationManager implements AuthenticationManager {

  static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();

  static {
    AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
  }

  public Authentication authenticate(Authentication auth) throws AuthenticationException {
    if (auth.getName().equals(auth.getCredentials())) {
      return new UsernamePasswordAuthenticationToken(auth.getName(),
        auth.getCredentials(), AUTHORITIES);
      }
      throw new BadCredentialsException("Bad Credentials");
  }

}

我们写了一个小程序,要求用户输入用户名和密码并执行上述序列。我们实现的 AuthenticationManager 会验证用户名和密码是否一致,它分配了一个角色给每个用户。上面的输出类似于这样:


Please enter your username:

favboy

Please enter your password:

favccxx

Authentication failed: Bad Credentials

Please enter your username:

favboy

Please enter your password:

favboy

Successfully authenticated. Security context contains: \

org.springframew[email protected]441d0230: \

Principal: bob; Password: [PROTECTED]; \

Authenticated: true; Details: null; \

Granted Authorities: ROLE_USER

注意,你通常不需要写任何代码。这个过程通常发生在内部,如web身份认证过滤器。上面的代码仅仅是告诉我们在Spring Security中使用身份认证是如此简单的事情。当 SecurityContextHolder 包含一个填充的 Authentication 对象时用户身份就完成了。

2. 直接设置 SecurityContextHolder的内容

实际上,Spring Security并不关心如何将 Authentication对象放到SecurityContextHolder中。唯一的关键就是 SecurityContextHolder需要在用户操作认证的 AbstractSecurityInterceptor 之前已经有了Authentication对象。

对于那些不是Spring Security的系统,你可以自己写过滤器或MVC控制器与身份认证系统进行集成。比如,你可能使用容器管理的身份认证系统从ThreadLocal或JNDI中得到用户。也可能你在一个拥有遗留的身份认证系统的公司工作,这是一个企业的“标准”,对此你是无能为力的。在这种情形下,使用Spring Security提供身份认证是非常容易的,你只需要写一个过滤器读取第三方的用户信息,然后构建一个Spring Security特定的 Authentication对象,并把它放到AuthenticationContextHolder中即可。在这种情况下,你需要考虑自带的身份认证的基础信息。比如,你需要在响应到客户端之前,先创建一个HTTP
session会话在请求之间缓存上下文。

3 在Web应用中使用身份认证

接下来,我们探究一下Web应用不配置web.xml安全策略的情况下如何使用Spring Security进行身份认证,如何建立用户身份认证和安全上下文?

下面是web应用身份认证的流程:

(1)访问某应用的首页,点击某个链接。

(2)发送一个请求到服务器,服务器判断用户是否正在访问受保护的资源。

(3)由于用户之前并未进行身份认证,服务器发送一个响应(该响应可能是HTTP响应代码,也可能直接跳转到某web页面)告诉用户必须进行身份认证。

(4)身份认证机制决定了浏览器是跳转到特定的web页面让用户填写form表单,或者浏览器以某种方式(基本的身份认证对话框、cookie或X.509证书)检索用户身份。

(5)浏览器发送响应(包含表单信息的HTTP POST请求或是包含用户身份认证详细信息的HTTP表头)回服务器。

(6)接下来,服务器会决定之前的凭证是否有效。如果有效的话,会进行下一步。否则的话,浏览器通常会询问是否需要重试。

(7)原始的请求会导致身份认证流程重新进行,重新判断用户有足够的权限访问受保护的资源,如果用户有权限的话,请求就是成功的。否则的话,会返回HTTP错误码403,表示用户没有权限操作。

Spring Security有具体的类负责上面的步骤,主要的类有 ExceptionTranslationFilter , AuthenticationEntryPoint 和调用AuenticationManager 的“身份认证机制”。

3.1 ExceptionTranslationFilter

顾名思义,ExceptionTranslationFilter是处理Spring Security中异常的过滤器,这些异常都是由提供身份认证服务的 AbstractSecurityInterceptor 抛出。

3.2 AuthenticationEntryPoint

上面步骤3的操作中是 AuenticationEntryPoint 的职责,你能想象每个web应用都有默认的身份认证测试,每个主要的身份认证系统都有 AuthenticationEntryPoint 实现,通常执行步骤3中描述的行动之一。

3.3 身份认证机制

一旦你的浏览器提交了验证证书(HTTP表单 POST或 HTTP头),这需要服务器上的一些东西保存这些权限信息。但是现在进入上面的第6步,在Spring Security中我们有一个特定的名称,为了手机验证信息的操作。从一个用户代理中(通常是浏览器),引用它作为一个“验证机制”。例如基于表单的登陆或BASIC验证。一旦从用户代理出收集到验证细节, Authentication请求对象就会建立,然后提交给AuthenticationManager。

身份认证机制收到填充好的 Authentication 对象之后,它会认为请求合法,把 Authentication放到SecurityContextHolder中,然后重试原始的请求(第7步)。如另一方面, AuthenticationManager拒绝了请求,身份认证机制会让用户代理重试(第2步)。

3.4 在请求间保存 SecurityContext

根据应用类型,需要一个策略在用户操作之间保存security上下文。在典型的web应用中,一次用户登陆日志随后就由它的session id所确定,服务器为保持session会话会缓存主体信息。在Spring Security中,在请求间存储SecurityContext的职责落在了 SecurityContextPersistenceFilter上,默认情况下,SecurityContextPersistenceFilter会在HTTP请求中将上下文存储在HttpSession属性上。每次请求的上下文都会存储在
SecurityContextHolder上,而且,最重要的是,当请求完成时它会清除 SecurityContextHolder。为了安全方面考虑,用户不应该直接操作 HttpSession,这里有简单的方法实现-使用 SecurityContextHolder代替。

很多其他类型的应用(比如一个无状态的REST Web服务)不会使用HTTP会话,会在每次请求时重新验证。然而,将 SecurityContextPersistenceFilter包含了请求链中仍然是非常重要的,这样就会确保在每次请求后 SecurityContextHolder会被清空。

时间: 2024-10-12 20:48:51

说道说道SpringSecurity身份认证的相关文章

详解Spring Security进阶身份认证之UserDetailsService(附源码)

在上一篇Spring Security身份认证博文中,我们采用了配置文件的方式从数据库中读取用户进行登录.虽然该方式的灵活性相较于静态账号密码的方式灵活了许多,但是将数据库的结构暴露在明显的位置上,绝对不是一个明智的做法.本文通过Java代码实现UserDetailsService接口来实现身份认证. 1.1 UserDetailsService在身份认证中的作用 Spring Security中进行身份验证的是AuthenticationManager接口,ProviderManager是它的

Spring Security身份认证之HelloSpringSecurity

在上一篇文档中,对Spring Security中的身份认证的流程和管理进行了详细介绍,本文将从实践的角度告诉大家如何使用最简便的方式用Spring Security进行身份验证. 开发环境如下: JDK 1.7 Tomcat 7 Eclipse Spring Security 3.2.5 项目目录结构如下: 1.新建Maven Project,对Maven不熟悉的童鞋请自行充电,现在这个念头不学习Maven绝对是不行的. 2. 在Pom.xml添加相关jar依赖. <project xmlns

Spring Security身份认证之UserDetailsService

zhiqian我们采用了配置文件的方式从数据库中读取用户进行登录.虽然该方式的灵活性相较于静态账号密码的方式灵活了许多,但是将数据库的结构暴露在明显的位置上,绝对不是一个明智的做法.本文通过Java代码实现UserDetailsService接口来实现身份认证. 1.1 UserDetailsService在身份认证中的作用 Spring Security中进行身份验证的是AuthenticationManager接口,ProviderManager是它的一个默认实现,但它并不用来处理身份认证,

Spring Security身份认证之HelloSpringSecurity(附源码)

在上一篇文档中,对Spring Security中的身份认证的流程和管理进行了详细介绍,本文将从实践的角度告诉大家如何使用最简便的方式用Spring Security进行身份验证. 开发环境如下: JDK 1.7 Tomcat 7 Eclipse Spring Security 3.2.5 项目目录结构如下: 1.新建Maven Project,对Maven不熟悉的童鞋请自行充电,现在这个念头不学习Maven绝对是不行的. 2. 在Pom.xml添加相关jar依赖. <project xmlns

NetScaler OTP双因子身份认证登录演示

NetScaler OTP 应用场景 NetScaler OTP(one time password)是双因子身份证的一种,利用用户名密码+6位时间型令牌认证码,完成身份认证. 在以前的双因子解决方案中NetScalerGateway需要与第三方 Radius服务器集成,实现双因子认证.对于客户来说,需要额外支付双因子身份认证的费用,提高了解决方案成本. NetScaler OTP解决方案利用NetScaler 源生功能,配合手机APP  google authenticator,不需要其他成本

TCP WRAPPERS、denyhosts软件的安装和配置、PAM身份认证模块应用

一.TCP WRAPPERS 1.TCP WRAPPERS的作用是什么? 保护服务器的一些服务,可以限制客户端访问这些服务. TCP WRAPPERS支持那些服务?判断一个服务是否支持TCP WRAPPERS的保护有那些方法? 查看该服务是否加载libwrap,查看该服务是不是基于xinetd服务. ssh ,vsftpd,telnet,http(不支持wrap模块)ipop3 2.检查服务是否支持被TCP WRAPPERS保护 3.防护规则存放在 /etc/hosts.allow /etc/h

使用nginx 的反向代理 给 kibana加上basic的身份认证

第一步准备工作 准备用户名密码: 更改host文件 第二步,安装nginx ubuntu安装Nginx之后的文件结构大致为:所有的配置文件都在/etc/nginx下,并且每个虚拟主机已经安排在了/etc/nginx/sites-available下启动程序文件在/usr/sbin/nginx日志放在了/var/log/nginx中,分别是access.log和error.log并已经在/etc/init.d/下创建了启动脚本nginx默认的虚拟主机的目录设置在了/usr/share/nginx/

基于oauth授权框架其中获取令牌需要发送Http身份认证的请求

1.首先我们基于curl的请求参数示例: curl http://localhost:8080/oauth/token -X POST -u client:fucksecurity -d "grant_type=refresh_token&refresh_token=1a1fb46e-8ab4-4a3b-84c4-e70892eaa570"其中的 -u 表示的是身份认证的用户名和密码.后来尝试过Jquery的$.ajax的username和password去传这个两个对象,发现

Core身份认证

Core中实现一个基础的身份认证 注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ASP.NET终于可以跨平台了,但是不是我们常用的ASP.NET, 而是叫一个ASP.NET Core的新平台,他可以跨Windows, Linux, OS X等平台来部署你的web应用程序,你可以理解为,这个框架就是ASP.NET的下一个版本,相对于传统ASP.NET