SSM框架下的shiro集成
shiro对于使用者,主要关注:subject:主体,代表当前'用户'SecurityManager:安全管理器,任何与安全相关操作都要与之交互,相当于dispacherServletRealm:域,shiro从realm中取安全数据(用户,角色,权限),相当于dataBaseShiro的其他支持特性AOP提供AOP方面的支持
·
shiro
对于使用者,主要关注:
subject:主体,代表当前'用户'
SecurityManager:安全管理器,任何与安全相关操作都要与之交互,相当于dispacherServlet
Realm:域,shiro从realm中取安全数据(用户,角色,权限),相当于dataBase
Shiro的其他支持特性
AOP提供AOP方面的支持,实现对某个类某个方法的拦截,从而使权限控制延伸至类的方法。
Cache提供缓存支持
Codec提供编码方面的支持
Crypto提供加密支持
IO从多个资源位置读写原始数据
JNDI提供jndi支持
util工具类支持
标签类用于Web页面
SSM环境下的认证
开发人员:
1、Subject类型的实例:
2、判断当前subject是否认证过
3、Subject login(token):
UsernamePasswordToken:当前用户输入的值
4、自定义Realm:获取数据库当中的数据
如果比对成功,不会出现任何异常,出现异常会出现认证异常
shiro API完成用户的认证
登录Controller中
1、获取subject类型的实例
Subject subject = SecurityUtils.getSubject();
2、判断用户是否登录
subject.isAuthenticated()
3、使用UsernamePasswordToken对象来封装用户名密码
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
4、使用Subject实例中的login(token)
subject.login(token);
5、Realm:从数据中获取安全数据
public class MyRealm extends AuthenticatingRealm{
@Autowired
private UserService usersvice;
/*
* 1.doGetAuthorizationInfo,获取认证消息,如果数据库中没有数据,返回null,如果得到正确的用户名密码,返回指定类型对象
*
* 2.AuthorizationInfo可以使用SimpleAuthenticationInfo实现类封装正确的用户名密码
*
* 3.token的参数,就是我们需要认证的token
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
SimpleAuthenticationInfo info=null;
// 1.将token转换成UserNamePasswordToken
UsernamePasswordToken upToken=(UsernamePasswordToken)token;
//2.获取用户名即可
String userName=upToken.getUsername();
//3.查询数据库,是否存在指定用户名密码用户
User user = usersvice.selectUser(userName);
if(user!=null){
//4.如果查询到了,封装查询结果,返回给我们调用
Object principal=user.getName();
Object credentials=user.getPassword();
String realmName=this.getName();
info=new SimpleAuthenticationInfo(principal, credentials, realmName);
}else{
//5.如果没查到,抛出异常
throw new AuthenticationException();
}
return info;
}
MD5加密
加密:MD5 SHA1
密码的对比:通过Realm的credentialsMatcher属性来进行密码的比对!
1.存储数据的时候,用户输入明文进行加密
2.前端yoghurt输入的值,进行加密,String类型字符串经过MD5得到一个值
shiro底层进行密码对比:用户输入值进行MD5加密
盐值加密:在原有算法基础上,加上唯一的盐值。
MD5盐值加密:即使两个用户密码一样,加密后的结果也不相同。
- 在doGetAuthenticationInfo方法返回值创建SimpleAuthenticationInfo对象时,需要使用
- SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realnName)构造器
- 使用ByteSource.Util.bytes()来计算
- 盐值需要唯一,如用户名或者随机数
- 使用new SimpleHash(hashAlgorithmName ,credentials, salt, hashIterations);来计算盐值加密后密码的值。
ByteSource salt=ByteSource.Util.bytes(userName);
SimpleHash sh= new SimpleHash("MD5", credentials, salt, 1024);
多Realm
多Realm获取数据:
意义:多个数据库中获取数据
多个realm,可能加密方式不同,这时需要认证策略,
是一个数据库验证算成功还是多个数据库验证都成功才算成功
第一种方式:
1.书写多个Realm实现类
2.SpringIoc容器中完成想要用的bean设置
<bean id="myRealm" class="com.ssm.shiro.MyRealm">
<!-- 前端输入调用Realm中的credentialsMatcher加密器对密码进行MD5加密1024次。 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
<bean id="secondRealm" class="com.ssm.shiro.SecondRealm">
<!-- 前端输入调用Realm中的credentialsMatcher加密器对密码进行MD5加密1024次。 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA1"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
3.seurityManager的bean中设置一个realms,并且通过集合对象完成属性注入。
<!-- 安全管理器,配置多个realm -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms" >
<list>
<ref bean="myRealm"/>
<ref bean="secondRealm"/>
</list>
</property>
</bean>
第二种方式:
1.需要配置一个认证器,ModularRealmAuthenticator
2.bean的realms属性完成注入
<!-- 安全管理器,配置多个realm -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="authenticator"></property>
</bean>
<!-- 声明一个认证器 -->
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="myRealm"/>
<ref bean="secondRealm"/>
</list>
</property>
</property name="authenticationStrategy" ref="allSuccessfulStrategy"></property>
</bean>
<bean id="allSuccessfulStrategy" class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean>
认证策略
AuthenticationStrategy:
FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略。
AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,将返回所有Realm身份验证成功的认证信息;
AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。
ModularRealmAuthenticator 默认是AtLeastOneSuccessfulStrategy策略
修改认证策略
第二种配置认证器黑色代码部分
授权roles拦截器
授权:控制哪一个用户可以访问哪一个web资源
tom-->adimin-->权限的web资源
jim--->user----->权限的web资源
主体:subject,用户
资源:可以访问的URL
权限:能干什么
角色:包含了多个权限
shiro支持三种方式授权
--编程式:通过写if/else授权代码块完成
if(subject.hasRole("admin")){
}else{
}
--注解式:通过在执行java方法上放置相应的注解完成,没有权限将抛出相应异常
@RequiresRoles("admin")
public void hello(){
}
--JSP/GSP 标签:在JSP/GSP页面通过相应的标签完成
<shiro:hasRole name="admin">
</shiro:hasRole>
默认拦截器
shiro内置了很多默认的拦截器,比如身份验证,授权等相关的。默认拦截器可以参考
org.apache.shiro.web.filter.mgt.DefaultFilter中的枚举拦截器
授权相关的拦截器
可以通过Ioc容器配置文件完成指定WEB资源对应的角色
filterChainDefinitions
web资源=roles[角色名称]
1.Ioc的配置文件中配置那些角色可以访问那些web资源,roles拦截器,roles[角色
]
/admin.jsp=roles[admin]
-登陆的用户如果拥有admin角色可以访问admin.jsp
2.一个用户进行登陆,认证成功以后,最终还是查找认证成功的用户拥有什么样的角色。
Realm可以帮助我们与数据库交互,获取认证成功的用户对应的角色。
-自定义一个Realm,继承AuthorizingRealm,认证和授权的工作。
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
//AuthorizationInfo 返回值封装获取用户对应的所有角色,SimpleAuthorizationInfo(Set<String>)
//参数列表PrincipalCollection 登陆的身份,即登陆的用户名
String name=principal.toString();
SimpleAuthorizationInfo info=null;
User user = usersvice.selectUser(name);
if(user!=null){
Set<String> roles=new HashSet<String>();
roles.add(user.getRoles());
info=new SimpleAuthorizationInfo(roles);
}else{
//5.如果没查到,抛出异常
throw new AuthenticationException();
}
return info;
}
-Ioc容器当中配置指定Realm的bean实例
上面已经定义myRealm
-告知securityManager使用哪一个授权管理器
配置一个授权管理器
<!-- 授权器 -->
<bean id="authorizer" class="org.apache.shiro.authz.ModularRealmAuthorizer">
<property name="realms">
<list>
<ref bean="myRealm"/>
<!-- <ref bean="secondRealm"/> -->
</list>
</property>
</bean>
告知sercurityManager,我要用到哪个授权器
<property name="authorizer" ref="authorizer"></property>
更多推荐
已为社区贡献2条内容
所有评论(0)