spring security总结.docx

上传人:b****5 文档编号:12358328 上传时间:2023-04-18 格式:DOCX 页数:28 大小:73.78KB
下载 相关 举报
spring security总结.docx_第1页
第1页 / 共28页
spring security总结.docx_第2页
第2页 / 共28页
spring security总结.docx_第3页
第3页 / 共28页
spring security总结.docx_第4页
第4页 / 共28页
spring security总结.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

spring security总结.docx

《spring security总结.docx》由会员分享,可在线阅读,更多相关《spring security总结.docx(28页珍藏版)》请在冰豆网上搜索。

spring security总结.docx

springsecurity总结

Springsecurity安全管理包括俩大部分,1,认证,2授权

1:

认证

认证的认证方法定义在一个接口中:

AuthenticationProvider这个接口定义了认证方法:

Authenticationauthenticate(Authenticationauthentication),要求认证传入参数类型是:

Authentication类型,

Authentication也是一个接口,该接口定义了认证相关的信息,如下:

GrantedAuthority[]getAuthorities();

权限主体拥有的权限,用户认证后权限实体将拥有一个保存了一系列GrantedAuthority对象的数组,之后可以用于进行验证用户是否可以访问系统中被保护资源。

GrantedAuthority接口内只有一个方法getAuthority(),它的返回值是一个字符串,这个字符串用来标识系统中的某一权限。

(这个字符串通常是ROLE_ADMIN,或者ROLE_USER),因为:

类GrantedAuthorityImpl实现接口GrantedAuthority,并实现方法StringgetAuthority(),

该实现类里面返回的权限是字符串Role_ADMIN等其他

ObjectgetCredentials();

获得权限主体的凭证,此凭证应该可以唯一标示权限主体。

默认情况下,凭证是用户的登录密码

ObjectgetDetails();

获得验证请求有关的附加信息。

默认情况下,附加信息是WebAuthenticationDetails的一个实例,其中保存了客户端ip和sessionid

ObjectgetPrincipal();

获得权限主体。

默认情况下,权限主体是一个实现了UserDetails接口的对象。

其中UserDetails接口定义如下:

GrantedAuthority[]getAuthorities();

返回授予该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来改变这个前缀。

如果读源代码的化,会发现:

这三个类都实现了同一个接口:

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提供了认证加密策略

如果使用认证加密,需要在配置文件里做如下配置:

 

加密工具类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包

用户信息缓存

beanid="userCache"class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">

propertyname="cache"ref="userEhCache"/>

bean>

beanid="userEhCache"class="org.springframework.cache.ehcache.EhCacheFactoryBean">

propertyname="cacheManager"ref="cacheManager"/>

propertyname="cacheName"value="userCache"/>

bean>

beanid="cacheManager"class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>

 

Springsecurity在获取用户权限的时候,可以通过不同的方式,获取,我们上面介绍的是通过Ldap服务器验证,还有一种是通过内存验证,只需在配置文件加入如下代码即可:

患有很多中认证方式,通常普遍的是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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 电子电路

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1