Now that we have a high-level overview of the Spring Security architecture and its core classes, let’s take a closer look at one or two of the core interfaces and their implementations, in particular the AuthenticationManagerUserDetailsService and the AccessDecisionManager. These crop up regularly throughout the remainder of this document so it’s important you know how they are configured and how they operate.

现在我们对Spring Security体系结构及其核心类进行了高级概述,让我们仔细研究一个或两个核心接口及其实现,特别是AuthenticationManager,UserDetailsS​​ervice和AccessDecisionManager。这些文件会在本文档的其余部分定期出现,因此了解它们的配置方式以及它们的运行方式非常重要。

10.1 The AuthenticationManager, ProviderManager and AuthenticationProvider

The AuthenticationManager is just an interface, so the implementation can be anything we choose, but how does it work in practice? What if we need to check multiple authentication databases or a combination of different authentication services such as a database and an LDAP server?

AuthenticationManager只是一个接口,因此实现可以是我们选择的任何东西,但它在实践中如何工作?如果我们需要检查多个身份验证数据库或不同身份验证服务(如数据库和LDAP服务器)的组合,该怎么办?
 
The default implementation in Spring Security is called ProviderManager and rather than handling the authentication request itself, it delegates to a list of configured AuthenticationProvider s, each of which is queried in turn to see if it can perform the authentication. Each provider will either throw an exception or return a fully populated Authentication object. Remember our good friends, UserDetails and UserDetailsService? If not, head back to the previous chapter and refresh your memory. The most common approach to verifying an authentication request is to load the corresponding UserDetails and check the loaded password against the one that has been entered by the user. This is the approach used by the DaoAuthenticationProvider (see below). The loaded UserDetails object - and particularly the GrantedAuthority s it contains - will be used when building the fully populated Authentication object which is returned from a successful authentication and stored in the SecurityContext.
Spring Security中的默认实现称为ProviderManager,它不是处理身份验证请求本身,而是委托给已配置的AuthenticationProvider列表,每个查询器依次查询它们是否可以执行身份验证。每个提供程序将抛出异​​常或返回完全填充的Authentication对象。还记得我们的好朋友,UserDetails和UserDetailsS​​ervice吗?如果没有,请回到上一章并刷新记忆。验证身份验证请求的最常用方法是加载相应的UserDetails并检查加载的密码与用户输入的密码。这是DaoAuthenticationProvider使用的方法(见下文)。加载的UserDetails对象 - 特别是它包含的GrantedAuthority - 将在构建完全填充的Authentication对象时使用,该对象从成功的身份验证返回并存储在SecurityContext中。
 
If you are using the namespace, an instance of ProviderManager is created and maintained internally, and you add providers to it by using the namespace authentication provider elements (see the namespace chapter). In this case, you should not declare a ProviderManager bean in your application context. However, if you are not using the namespace then you would declare it like so:
如果您正在使用命名空间,则会在内部创建和维护ProviderManager的实例,并使用命名空间身份验证提供程序元素向其添加提供程序(请参阅命名空间章节)。在这种情况下,您不应在应用程序上下文中声明ProviderManager bean。但是,如果您没有使用命名空间,那么您将声明它如下:
 
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="ldapAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>

In the above example we have three providers. They are tried in the order shown (which is implied by the use of a List), with each provider able to attempt authentication, or skip authentication by simply returning null. If all implementations return null, the ProviderManager will throw a ProviderNotFoundException. If you’re interested in learning more about chaining providers, please refer to the ProviderManager Javadoc.

在上面的例子中,我们有三个提供者。它们按所示顺序(使用List暗示)进行尝试,每个提供程序都可以尝试进行身份验证,或者通过简单地返回null来跳过身份验证。如果所有实现都返回null,则ProviderManager将抛出ProviderNotFoundException。如果您有兴趣了解有关链接提供程序的更多信息,请参阅ProviderManager Javadoc。
 
Authentication mechanisms such as a web form-login processing filter are injected with a reference to the ProviderManager and will call it to handle their authentication requests. The providers you require will sometimes be interchangeable with the authentication mechanisms, while at other times they will depend on a specific authentication mechanism. For example, DaoAuthenticationProvider and LdapAuthenticationProvider are compatible with any mechanism which submits a simple username/password authentication request and so will work with form-based logins or HTTP Basic authentication. 
诸如Web表单登录处理过滤器之类的身份验证机制将引用ProviderManager,并将其调用以处理其身份验证请求。您需要的提供程序有时可以与身份验证机制互换,而在其他时候,它们将依赖于特定的身份验证机制。例如,DaoAuthenticationProvider和LdapAuthenticationProvider与提交简单用户名/密码身份验证请求的任何机制兼容,因此可以使用基于表单的登录或HTTP基本身份验证。
 
On the other hand, some authentication mechanisms create an authentication request object which can only be interpreted by a single type of AuthenticationProvider. An example of this would be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be authenticated by a CasAuthenticationProvider. You needn’t be too concerned about this, because if you forget to register a suitable provider, you’ll simply receive a ProviderNotFoundException when an attempt to authenticate is made.
另一方面,某些身份验证机制会创建一个身份验证请求对象,该对象只能由单一类型的AuthenticationProvider进行解释。这方面的一个例子是JA-SIG CAS,它使用服务票据的概念,因此只能由CasAuthenticationProvider进行身份验证。您不必过于担心这一点,因为如果您忘记注册合适的提供程序,那么在尝试进行身份验证时,您只会收到ProviderNotFoundException。

10.1.1 Erasing Credentials on Successful Authentication

By default (from Spring Security 3.1 onwards) the ProviderManager will attempt to clear any sensitive credentials information from the Authentication object which is returned by a successful authentication request. This prevents information like passwords being retained longer than necessary.

默认情况下(从Spring Security 3.1起),ProviderManager将尝试从Authentication对象中清除任何敏感凭证信息,该信息由成功的身份验证请求返回。这可以防止密码保留的时间超过必要的时间。
 
This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application. If the Authentication contains a reference to an object in the cache (such as a UserDetails instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value. You need to take this into account if you are using a cache. An obvious solution is to make a copy of the object first, either in the cache implementation or in the AuthenticationProvider which creates the returned Authentication object. Alternatively, you can disable the eraseCredentialsAfterAuthenticationproperty on ProviderManager. See the Javadoc for more information.
当您使用用户对象的缓存时,这可能会导致问题,例如,提高无状态应用程序的性能。如果身份验证包含对缓存中对象的引用(例如UserDetails实例)并且已删除其凭据,则将无法再对缓存的值进行身份验证。如果使用缓存,则需要考虑这一点。一个显而易见的解决方案是首先在缓存实现中或在创建返回的Authentication对象的AuthenticationProvider中制作对象的副本。或者,您可以在ProviderManager上禁用eraseCredentialsAfterAuthentication属性。有关更多信息,请参阅Javadoc。
 

10.1.2 DaoAuthenticationProvider

The simplest AuthenticationProvider implemented by Spring Security is DaoAuthenticationProvider, which is also one of the earliest supported by the framework. It leverages a UserDetailsService (as a DAO) in order to lookup the username, password and GrantedAuthority s. It authenticates the user simply by comparing the password submitted in a UsernamePasswordAuthenticationToken against the one loaded by the UserDetailsService. Configuring the provider is quite simple:

Spring Security实现的最简单的AuthenticationProvider是DaoAuthenticationProvider,它也是该框架最早支持的之一。它利用UserDetailsS​​ervice(作为DAO)来查找用户名,密码和GrantedAuthority。它只是通过将UsernamePasswordAuthenticationToken中提交的密码与UserDetailsS​​ervice加载的密码进行比较来对用户进行身份验证。配置提供程序非常简单:
 
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="inMemoryDaoImpl"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>

The PasswordEncoder is optional. A PasswordEncoder provides encoding and decoding of passwords presented in the UserDetails object that is returned from the configured UserDetailsService. This will be discussed in more detail below.

PasswordEncoder是可选的。 PasswordEncoder提供从配置的UserDetailsS​​ervice返回的UserDetails对象中显示的密码的编码和解码。这将在下面更详细地讨论。

10.2 UserDetailsService Implementations

As mentioned in the earlier in this reference guide, most authentication providers take advantage of the UserDetails and UserDetailsService interfaces. Recall that the contract for UserDetailsService is a single method:

如本参考指南前面所述,大多数身份验证提供程序都利用UserDetails和UserDetailsS​​ervice接口。回想一下UserDetailsS​​ervice的合同是一个单一的方法:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

The returned UserDetails is an interface that provides getters that guarantee non-null provision of authentication information such as the username, password, granted authorities and whether the user account is enabled or disabled. Most authentication providers will use a UserDetailsService, even if the username and password are not actually used as part of the authentication decision. They may use the returned UserDetails object just for its GrantedAuthority information, because some other system (like LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the credentials.

返回的UserDetails是一个接口,提供保证非空提供身份验证信息的getter,例如用户名,密码,授予的权限以及是启用还是禁用用户帐户。大多数身份验证提供程序将使用UserDetailsS​​ervice,即使用户名和密码实际上未用作身份验证决策的一部分。他们可能仅仅为了GrantedAuthority信息使用返回的UserDetails对象,因为其他一些系统(如LDAP或X.509或CAS等)承担了实际验证凭据的责任。
 
Given UserDetailsService is so simple to implement, it should be easy for users to retrieve authentication information using a persistence strategy of their choice. Having said that, Spring Security does include a couple of useful base implementations, which we’ll look at below.
鉴于UserDetailsS​​ervice实现起来非常简单,用户应该可以使用自己选择的持久性策略轻松检索身份验证信息。话虽如此,Spring Security确实包含了一些有用的基础实现,我们将在下面介绍。

10.2.1 In-Memory Authentication

Is easy to use create a custom UserDetailsService implementation that extracts information from a persistence engine of choice, but many applications do not require such complexity. This is particularly true if you’re building a prototype application or just starting integrating Spring Security, when you don’t really want to spend time configuring databases or writing UserDetailsService implementations. For this sort of situation, a simple option is to use the user-service element from the security namespace:

易于使用创建自定义UserDetailsS​​ervice实现,从实际选择的持久性引擎中提取信息,但许多应用程序不需要这样的复杂性。如果您正在构建原型应用程序或刚刚开始集成Spring Security,而您真的不想花时间配置数据库或编写UserDetailsS​​ervice实现,则尤其如此。对于这种情况,一个简单的选择是使用安全命名空间中的user-service元素:
 
<user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>

This also supports the use of an external properties file:

这也支持使用外部属性文件:
 
<user-service id="userDetailsService" properties="users.properties"/>

The properties file should contain entries in the form

属性文件应包含表单中的条目
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]

For example

jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled

10.2.2 JdbcDaoImpl

Spring Security also includes a UserDetailsService that can obtain authentication information from a JDBC data source. Internally Spring JDBC is used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to store user details. If your application does use an ORM tool, you might prefer to write a custom UserDetailsService to reuse the mapping files you’ve probably already created. Returning to JdbcDaoImpl, an example configuration is shown below:

Spring Security还包括一个UserDetailsS​​ervice,它可以从JDBC数据源获取身份验证信息。内部使用Spring JDBC,因此它避免了全功能对象关系映射器(ORM)的复杂性,只是为了存储用户详细信息。如果您的应用程序确实使用ORM工具,您可能更愿意编写自定义UserDetailsS​​ervice来重用您可能已经创建的映射文件。返回JdbcDaoImpl,示例配置如下所示:
 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean> <bean id="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>

You can use different relational database management systems by modifying the DriverManagerDataSource shown above. You can also use a global data source obtained from JNDI, as with any other Spring configuration.

您可以通过修改上面显示的DriverManagerDataSource来使用不同的关系数据库管理系统。您还可以使用从JNDI获取的全局数据源,与任何其他Spring配置一样。

Authority Groups

By default, JdbcDaoImpl loads the authorities for a single user with the assumption that the authorities are mapped directly to users (see the database schema appendix). An alternative approach is to partition the authorities into groups and assign groups to the user. Some people prefer this approach as a means of administering user rights. See the JdbcDaoImpl Javadoc for more information on how to enable the use of group authorities. The group schema is also included in the appendix.

默认情况下,JdbcDaoImpl为单个用户加载权限,并假设权限直接映射到用户(请参阅数据库模式附录)。另一种方法是将权限划分为组并将组分配给用户。有些人更喜欢这种方法来管理用户权利。有关如何启用组权限的更多信息,请参阅JdbcDaoImpl Javadoc。组架构也包含在附录中。

Spring Security(三十二):10. Core Services的更多相关文章

  1. Spring Security(十二):5. Java Configuration

    General support for Java Configuration was added to Spring Framework in Spring 3.1. Since Spring Sec ...

  2. 精选Spring Boot三十五道必知必会知识点

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家.本文精选了三十五个常见的Spring Boot知识点,祝你一臂之力! 问题一 Spr ...

  3. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  4. Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

    Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版]  发表于 2018-04-24 |  随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请 ...

  5. [转]Spring Security学习总结二

    原文链接: http://www.blogjava.net/redhatlinux/archive/2008/08/20/223148.html http://www.blogjava.net/red ...

  6. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  7. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. ASP 三十二条精华代码 (1)

    ASP 三十二条精华代码 (1) 2009-08-10 09:53:03  www.hackbase.com  来源:互联网 1. oncontextmenu="window.event.r ...

  10. “全栈2019”Java第三十二章:增强for循环Foreach语法

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. synchronized底层实现学习

    上文我们总结了 synchronized 关键字的基本用法以及作用,并未涉及 synchronized 底层是如何实现的,所谓刨根问底,本文我们就开始 synchronized 原理的探索之旅吧(*& ...

  2. Linux下的C#连接Mysql数据库

    今天在尝试在 Linux 系统下使用C#连接数据库,发现网上这方面的信息很少,所以就写一篇博客记录一下. Linux下这里使用的是mono. 首先是缺少Mysql.Data.dll这个库的,所以需要安 ...

  3. kubernetes系列05—kubectl应用快速入门

    本文收录在容器技术学习系列文章总目录 1.使用kubectl 1.1 介绍 kubectl用于运行Kubernetes集群命令的管理工具. 1.2 语法 kubectl [command] [TYPE ...

  4. 应用集成mycat,实现mycat的高可用与mysql的读写分离

    前言 开心一刻 一个女人自朋友圈写道:我家老公昨天和别人家的老婆出去旅游,迄今未归,我则被别人家的老公折腾了一天,好累哦! 圈子下面,评论无数,老公在下面评论到:能不能好好说话,我只不过陪女儿去毕业旅 ...

  5. 【Zabbix】Zabbix Server自动发现

    Zabbix自动发现 由于有上百台的虚拟机需要监控,如果一个个去添加配置,费时费力.Zabbix的自动发现,可以自动发现需要监控的机器,监控相应指标. 前置条件 安装部署好Zabbix Server. ...

  6. frame buffer简单应用

    现在我们要在LCD上画一个点,我们无法直接对LCD屏进行操作.这时候就需要用到FrameBuffer,Linux可以FrameBuffer这个设备来供用户态进程实现直接写屏.首先我们先简单看一下lin ...

  7. 商汤科技汤晓鸥:其实不存在AI行业,唯一存在的是“AI+“行业

    https://mp.weixin.qq.com/s/bU-TFh8lBAF5L0JrWEGgUQ 9 月 17 日,2018 世界人工智能大会在上海召开,在上午主论坛大会上,商汤科技联合创始人汤晓鸥 ...

  8. C# MessageBox自动关闭

    本文以一个简单的小例子,介绍如何让MessageBox弹出的对话框,在几秒钟内自动关闭.特别是一些第三方插件(如:dll)弹出的对话框,最为适用.本文仅供学习分享使用,如有不足之处,还请指正. 概述 ...

  9. python集合使用范例的代码

    在代码过程中中,将代码过程中比较好的代码段珍藏起来,如下的代码是关于python集合使用范例的代码,希望能对大伙有用. # sets are unordered collections of uniq ...

  10. 商家APP店内点餐开启有桌台点餐模式

    商家APP店内点餐开启有桌台点餐模式 步骤一:管理员后台-配置管理--店铺配置--简易付tab页--是否支持扫码下单-是 步骤二:管理员后台-配置管理--设备管理--选择对应的机器--配置--云POS ...