官网:shiro.apache.org
一、shiro介绍
1.shiro框架的核心功能:认证、授权、会话管理、加密
2.shiro框架认证流程:
3.涉及的相关概念和类
ApplicationConde,应用程序代码,由开发人员进行开发
Subject,框架提供的接口,代表当前用户对象
SecurityManager,框架提供的接口,代表安全管理器,是shiro框架最核心的对象
Realm,可以开发人员编写,框架也提供一些,类似于DAO,用于访问权限数据
4.导包方式:只要导入shiro-all,相当于导入了所有的分包
二、shiro相关配置简单介绍
ShiroFilterFactoryBean:是一个工厂类,用于创建过滤器,进行权限拦截,要求对其注入SecurityManager,以及三个URL
authc过滤器为shiro过滤器类的别名,用于检查用户是否认证过(俗称的登录) - 此时可以取消自己编写的登录过滤器了
anon过滤器为匿名访问过滤器,表示不登录也能访问资源
perms过滤器用于检查权限,用于检查登录用户是否具有对应的权限:/page_base_staff.action = perms["staff-list"]
**表示多级子目录
validatecode.jsp*表示通配(用于匹配不同的参数参数)
三、在bos项目中使用shiro框架进行认证
1.在porm.xml中引入对shiro框架的依赖
<!-- 引入shiro框架的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
2.在web.xml中配置过滤器,Spring提供的,用于整合shiro框架,注意要放在struts2过滤器的前面
<!-- 配置Spring框架提供的用于整合shiro框架的过滤器 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.配置完过滤器后,会要求Spring工厂提供一个对应名称(如按上述配置就是shiroFilter)的Bean,若不提供则项目启动报错
4.对于shiroFilter,要为其注入securityManager、相关URL以及URL的拦截规则
<!-- 配置shiro框架的工厂对象 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"></property>
<!-- 注入相关页面访问URL -->
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/index.jsp"/>
<property name="unauthorizedUrl" value="unauthorized.jsp"/>
<!-- 注入URL拦截规则 -->
<property name="filterChainDefinitions">
<value>
/css/** = anon
/js/** = anon
/images/** = anon
/validatecode.jsp* = anon
/login.jsp = anon
/userAction_login.action = anon
/page_base_staff.action = perms["staff-list"]
/* = authc
</value>
</property>
</bean>
5.对于securityManager,需要为其注入realm,该reaml可以是自定义的,也可以是框架提供的
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="bosRealm"></property>
</bean>
6.编写自定义的Realm
public class BosRealm extends AuthorizingRealm{
//认证方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken arg0) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) arg0;
//获得页面输入的用户名
String username = token.getUsername();
//根据用户名从数据库查询实体
User user = userDao.findByUsername(username);
if(user == null){
//页面输入的用户名不存在
return null;
}
//框架负责检验输入和数据库查询出来的对象是否一致
//简单认证信息对象
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
//返回信息对象,由安全管理器调用认证器进行信息认证
return info;
}
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
return null;
}
@Autowired
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
7.配置自定义的bosRealm
<bean id="bosRealm" class="com.hao.bos.realm.BosRealm"/>
8.重写UserAction的登录方法,利用shiroFilter进行登录的过滤
/**
* 用户登录,使用shiro框架提供的方式进行认证
*
* @return
*/
public String login() {
// 先校验验证码是否输入正确
String validatecode = (String) session.get("key");
if (StringUtils.isNotBlank(checkcode) && checkcode.equals(validatecode)) {
// 使用shiro框架提供的方式进行认证
// 获得当前用户对象,里面包含认证状态
Subject subject = SecurityUtils.getSubject();
// 创建用户名密码令牌对象
AuthenticationToken token = new UsernamePasswordToken(model.getUsername(), MD5Utils.md5(model.getPassword()));
try {
subject.login(token);
} catch (UnknownAccountException e) {
this.addActionError("用户名不存在!");
return LOGIN;
} catch (IncorrectCredentialsException e) {
this.addActionError("密码输入错误!");
return LOGIN;
} catch (Exception e) {
this.addActionError("发生未知错误!");
return LOGIN;
}
//取得查询出来的User对象,放到Session
User user = (User) subject.getPrincipal();
session.put("loginUser", user);
return HOME;
} else {
// 输入验证码错误。设置提示信息,
this.addActionError("输入的验证码错误");
return LOGIN;
}
}
四、在BosRealm中完成授权
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
//创建授权信息对象
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加具体的授权信息
info.addStringPermission("staff-list");
//TODO 后期需要修改为根据当前用户查询数据库,获取实际对应的权限
//返回授权信息对象
return info;
}