spring security总结Word文档格式.docx
- 文档编号:3201526
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:28
- 大小:73.78KB
spring security总结Word文档格式.docx
《spring security总结Word文档格式.docx》由会员分享,可在线阅读,更多相关《spring security总结Word文档格式.docx(28页珍藏版)》请在冰点文库上搜索。
其中UserDetails接口定义如下:
返回授予该user的权限
StringgetPassword();
返回被用来认证该用户的密码
StringgetUsername();
返回被用来认证该用户的用户名
booleanisAccountNonExpired();
指出用户的账号是否过期,过期的账号不能被认证,识别
booleanisAccountNonLocked();
指出用户是否被锁定,被锁定的用户不能通过认证。
booleanisCredentialsNonExpired();
指出用户的密码是否过期,也就是说判断该用户的密码是否正确。
无效的密码将被组织通过认证。
booleanisEnabled();
指出用户是否被禁用,禁用的用户不能通过认证。
上面谈到的是认证的接口类AuthenticationProvider,而这个接口类又有不同的实现,所以在springsecurity中很多中认证机制:
一:
匿名用户认证:
classAnonymousAuthenticationProvider,该类提供了匿名用户登陆的认证方式,
classRememberMeAuthenticationProvider,该类提供了自动登陆认证方式,
classRemoteAuthenticationProvider,该类提供了远程认证方式
classDaoAuthenticationProvider,该类实现form表单认证方式,
classLdapAuthenticationProvider,该类实现了Ldap认证方式,
等等,还有其他认证不是很常用,我们这里主要的认证方式就后面这俩个认证方式。
我们这里主要谈谈Ldap认证即LdapAuthenticationProvider:
LdapAuthenticationProvider是AuthenticationProvider的ldap认证方式的实现。
而在LdapAuthenticationProvider内部有是使用了不同的认证方式的,它有两个实现,分别对应于LDAP的两种认证方式:
bind(BindAuthenticator)和passwordcompare(PasswordComparisonAuthenticator)。
SpringSecurity缺省的schema配置使用的是bind认证。
如果使用passwordcompare方式认证,需要指定如何获取口令。
LDAP的俩种认证方式定义在一个接口中,这个接口是:
interfaceLdapAuthenticator,它只提供了一个认证方法:
DirContextOperationsauthenticate(Authenticationauthentication);
不用多说,一看就明白。
SpringSecurity在认证成功后,将票据存放在SecurityContext中。
SecurityContext是一个接口,
这里又出现了新的SecurityContext安全上下文:
为使所有的组件都可以通过同一方式访问当前的权限实体,SpringSecurity特别提供了SecurityContext作为安全上下文,
可以直接通过SecurityContextHolder获得当前线程中的SecurityContext。
SecurityContextsecurityContext=SecurityContextHolder.getContext();
默认情况下,SecurityContext的实现基于ThreadLocal,系统会在每次用户请求时将SecurityContext与当前Thread进行绑定,也可以调用SecurityContextHolder的setStrategyName()方法来修改系统使用的策略。
SecurityContextHolder.setStrategyName("
MODE_GLOBAL"
);
如果用户尚未通过认证,那么SecurityContext.getAuthenticaiton()方法就会返回null。
可以使用Authentication接口中定义的几个方法,获得当前权限实体的信息
这个前面已经说过,不在重复。
从接口的方法可以看出,用户可以通过SecurityContext存放和读取票据信息(Authentication)。
SecurityContext又存放在SecurityContextHolder。
SecurityContextHolder定义了SecurityContext
的相关操作,如初始化,清空,读取等。
SecurityContextHolder并没有直接实现这些操作,而是使用了策略模式,
由一个SecurityContextHolderStrategy接口,来完成真正的逻辑。
SpringSecurity提供了3个实现:
GlobalSecurityContextHolderStrategy,在这种策略下,JVM所有的对象共享一个SecurityContext对象。
一般在胖客户端使用,一个客户端就是一个用户代理。
ThreadLocalSecurityContextHolderStrategy,这种策略下,每个线程关联一个SecurityContext。
每次都从当前线程读取或存放SecurityContext。
一般用于为多个用户服务的服务器,每个用户一个线程。
是最常用的模式,也是SpringSecurity缺省的策略。
用户注销时,应该把该用户所在线程的SecurityContext清除掉。
InheritableThreadLocalSecurityContextHolderStrategy,这种策略是InheritableThreadLocal版本的实现。
有两种方法可以设置策略:
1)用要使用策略的类名作为系统属性spring.security.strategy的值。
2)直接
调用SecurityContextHolder的静态方法setStrategyName。
认证完成通过LdapAuthoritiesPopulator来获取用户权限,其中LdapAuthoritiesPopulator也是一个接口,定义如下:
interfaceLdapAuthoritiesPopulator,该接口定义了唯一的方法
GrantedAuthority[]getGrantedAuthorities(DirContextOperationsuserData,Stringusername);
它有三个实现。
其中一个是一个空实现,不返回任何权限信息。
另外两个实现对应的授权信息的两个来源。
如果授权信息从LDAP中获取,则使用DefaultLdapAuthoritiesPopulator,如果用户权限从外部的UserDetailsService中获取,则使用UserDetailsServiceLdapAuthoritiesPopulator。
其中DefaultLdapAuthoritiesPopulator从LDAP中获取的权限前面会添加上前缀,缺省值为"
ROLE_"
。
谈到这里不得不提一下,为什么权限前面会添加前缀,而其缺省值为:
ROLE_,实际上这与SpringSecurity中的Voter机制有着千丝缕的联系
Voter表决者(投票器的概念)
AccessDecisionManager维护着一个AccessDecisionVoter列表参与授权的投票。
根据处理投票的策略不同
interfaceAccessDecisionVoter定义了方法:
intvote(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig);
SpringSecurity中AccessDecisionManager有3个不同的实现。
如下:
UnanimousBased.java只要有一个Voter不能完全通过权限要求,就禁止访问。
AffirmativeBased.java只要有一个Voter可以通过权限要求,就可以访问。
ConsensusBased.java只要通过的Voter比禁止的Voter数目多就可以访问了。
AccessDecisionVoter的vote方法,实现了投票的逻辑。
vote方法需要的参数AccessDecisionManager的decide方法
完全相同。
实际上AccessDecisionManager的功能就是委托给AccessDecisionVoter实现的。
SpringSecurity中有很多AccessDecisionVoter的实现,最简单的有RoleVoter。
RoleVoter通过将Authentication里面获取的权限信息,与从
ConfigAttributeDefinition配置的访问资源需要的权限对比,来投票通过,或拒绝,或弃权。
RoleVoter默认角色名称都是以ROLE_开头
稍微注意一下,默认角色名称都要以ROLE_开头,否则不会被计入权限控制,如果需要修改,就在xml里配个什么前缀的。
可以用过配置roleVoter的rolePrefix来改变这个前缀。
<
beanid="
roleVoter"
class="
org.springframework.security.vote.RoleVoter"
>
<
propertyname="
rolePrefix"
value="
AUTH_"
/>
/bean>
如果读源代码的化,会发现:
这三个类都实现了同一个接口:
interfaceAccessDecisionManager,这个接口又是干什么的呢?
AccessDecisionManager完成授权的功能。
观察AccessDecisionManager接口的授权方法:
voiddecide(Authenticationauthentication,Objectobject,ConfigAttributeDefinitionconfig)
对一次访问授权,需要传入三个信息。
(1)认证过的票据Authentication,确定了谁正在访问资源。
(2)被访问的资源object。
(3)访问资源要求的权限配置ConfigAttributeDefinition。
从票据中可以获取认证用户所拥有的权限,再对比访问资源要求的权限,即可断定当前认证用户是否能够访问该资源。
返回认证:
认证的过程涉及到认证方法,认证需要提供的凭证信息,和认证的后的票据
AuthenticationManager是认证的入口,这个接口只有一个方法
Authenticationauthenticate(Authenticationauthentication)。
凭证信息:
凭证信息包括用户名,密码,证书或其他信息。
观察AuthenticationManager接口,authenticate方法接收一个Authentication类型的参数,
Authentication有一个方法getCredentials(),返回Object,这就是凭证信息。
Authentication对象是存放凭证信息的地方。
SpringSecurity没有规定认证方法,认证启动后会调用AuthenticationManager.authenticate方法,实现认证。
SpringSecurity提供了一个缺省的实现ProviderManager,管理一个AuthenticationProvider的列表。
真正认证的功能代理给AuthenticationProvider完成(文章头部),每个AuthenticationProvider提供了真正的认证逻辑。
缺省的实现中只要有一个AuthenticationProvider证成功,ProviderManager就认为认证成功,并返回票据。
SpringSecurity提供了一些默认的AuthenticationProvider的实现,如DaoAuthenticationProvider,LdapAuthenticationProvider等,分别对应不同的认证方法。
票据是一个用户身份标识,系统根据用户的票据为用户授权。
AuthenticationManager的authenticate返回一个Authentication作为票据,包含了认证过的Principal和权限(GrantedAuthority)信息。
实际上Authentication自身就是一个Principal(实现了java.security.Principal接口)。
在认证的时候,springsecurity提供了认证加密策略
如果使用认证加密,需要在配置文件里做如下配置:
authentication-provider>
password-encoderhash="
md5"
salt-sourceuser-property="
username"
/password-encoder>
jdbc-user-servicedata-source-ref="
dataSource"
/authentication-provider>
加密工具类interfacePasswordEncoder,该接口定义了方法加密和解密
StringencodePassword(StringrawPass,Objectsalt)
booleanisPasswordValid(StringencPass,StringrawPass,Objectsalt)
该接口的实现类很多,不同的实现类实现不同的加密手段:
我们常用的是MD5加密
PasswordEncoder和SaltValue
默认提供的PasswordEncoder包含plaintext,sha,sha-256,md5,md4,{sha},{ssha}。
其中{sha}和{ssha}是专门为ldap准备的,plaintext意味着不对密码进行加密,
如果我们不设置PasswordEncoder,默认就会使用它。
SaltValue是为了让密码加密更加安全,它有两种策略可以选择。
user-property,system-wide分别对应着ReflectionSaltSource和SystemWideSaltSource,
它们的区别是ReflectionSaltSource会使用反射,从用户的Principal对象汇总取出一个对应的属性来作为盐值,
而SystemWideSaltSource会为所有用户都设置相同的盐值。
使用了PasswordEncoder和SaltValue的结果就是数据库中的密码变得难以辨认了,
这就要注意在添加用户时要使用相同的策略对密码进行加密,这才能保证新用户可以正常登陆。
Springsecurity还提供了缓冲机制,用于用户信息缓存,有关缓冲的定义在接口
UserCache中,类EhCacheBasedUserCache实现了缓冲接口中的方法,具体实现是依赖与spring的缓冲jar包
用户信息缓存
cache-ref="
userCache"
beans:
org.springframework.security.providers.dao.cache.EhCacheBasedUserCache"
cache"
ref="
userEhCache"
/beans:
bean>
org.springframework.cache.ehcache.EhCacheFactoryBean"
cacheManager"
cacheName"
org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
Springsecurity在获取用户权限的时候,可以通过不同的方式,获取,我们上面介绍的是通过Ldap服务器验证,还有一种是通过内存验证,只需在配置文件加入如下代码即可:
user-service>
username="
admin"
password="
authorities="
ROLE_USER,ROLE_ADMIN"
/>
user"
ROLE_USER"
/user-service>
患有很多中认证方式,通常普遍的是JDBC数据库验证,
到这里该提下这个接口UserDetailsService,这个接口用与获取用户的权限信息或者说主体信息,该借口定义了唯一的方法:
UserDetailsloadUserByUsername(Stringusername)
接口UserDetailsManager继承了接口UserDetailsService,并新增添了一些方法:
voidcreateUser(UserDetailsuser);
voidupdateUser(UserDetailsuser);
voiddeleteUser(Stringusername);
booleanuserExists(Stringusername);
等等,于此相对应的也有一个接口GroupManager,用与对组的CRUD操作,
String[]findAllGroups();
String[]findUsersInGroup(StringgroupName);
voidcreateGroup(StringgroupName,GrantedAuthority[]authorities);
voiddeleteGroup(StringgroupName);
等等,springsecurity把用户和组的概念结合起来了,有组的概念,权限组?
JdbcUserDetailsManager实现接口UserDetailsManager,GroupManager,继承类JdbcDaoImpl
JdbcDaoImpl类继承类JdbcDaoSupport实现接口UserDetailsSdervice
抽象类JdbcDaoSupport继承DaoSupport
JdbcDaoSupplor中成员变量JdbcTemplate实现连接数据库
所以如果我们自己程序里用springsecurity,
可以使用JdbcTemplate,UserDetailsManager,但需要实现他的一个接口
interfaceUserDetailsService
说的在详细点:
UserDetailsManager接口定义了User的增删改查方法,并继承了接口UserDetailsService接口,
JdbcUserDetailsManager类继承了JdbcDaoImpl,实现了接口UserDetailsManager,GroupManager
GroupManager接口定义了组的增删改查和用户与组之间的关系
JdbcUserDetailsManager实现了User的增删改查方法和组的增删改查,通过调用getJdbcTemplate完成的,而getJdbcTemplate是JdbcTemplate类,该类实现了数据库的底层,删除用户的时候会清理缓冲,缓冲类的接口是UserCache,该接口定义了从缓冲中获取用户,把用户存入缓冲,及从缓冲中删除用户等方法
EhCacheBasedUserCache类实现了UserCache接口,并实现了UserCache接口定义的方法
总结一下:
pringSecurity中的UserDetails被作为一个通用的权限主体,凡是涉及到username和password的情况,
都会使用到UserDetails和它对应的服务。
常用的服务有从内存中读取用户信息的InMemoryDaoImpl和用数据库中读取用户信息的JdbcDaoImp。
它们都实现了UserDetailsService,因此都可以使用loadUserByUsername()方法获得对应用户的信息。
InMemoryDaoImpl中读取权限主体是UserMap,而UserMap是一个Map类型,key放的是usern
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- spring security总结 security 总结