目录
(1)在web.xml中配置spring框架提供的用于整合shiro框架的过滤器
(2)整合Spring,配置bean:shiroFilter
(4)Controller层编写login方法,使用shiro提供的方式进行权限认证
1.Shiro框架的基本概念
Shiro框架的核心功能有4个,即认证、授权、会话管理、加密,shiro基本使用这一方面我们主要讨论认证与授权两个基本用法。认证,顾名思义,即登陆时期数据库用户对象与表单的用户对象比对,若对比成功,则登陆成功。授权,即登陆之后当前该用户能访问哪些请求,不能访问哪些请求,这些请求也是从数据库中查询的。
Application Code:应用程序代码,由开发人员负责开发
Subject:框架提供的接口,代表当前认证对象
SecurityManager:框架提供的接口,代表安全管理器对象
Realm:可以开发人员编写,框架也提供一些,类似于DAO,用户访问权限数据
2.Shiro的maven依赖与spring配置
2.1shiro的maven依赖
<!-- 引入shiro框架的依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
2.2Shiro的spring配置
(1)在web.xml中配置spring框架提供的用于整合shiro框架的过滤器
<!-- 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>
(2)整合Spring,配置bean:shiroFilter
<!-- 配置shiro框架的过滤器工厂对象 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入安全管理器对象 -->
<property name="securityManager" ref="securityManager" />
<!-- 注入相关页面访问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>
(3)注册安全管理器对象
<!-- 注册安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" />
(4)Controller层编写login方法,使用shiro提供的方式进行权限认证
public String login() {
/**
* 校验验证码
*/
//获取正确的验证码
String trueCode = (String) ActionContext.getContext().getSession().get("key");
//验证码校验不通过
if(trueCode != null && !trueCode.equals(checkCode)) {
this.addActionError("验证码错误");
return LOGIN;
}else {//验证码正确
//使用shiro提供的方式进行认证
Subject subject = SecurityUtils.getSubject();//获取当前用户对象,状态为“未认证”
//创建用户名密码令牌对象
AuthenticationToken token = new UsernamePasswordToken(model.getUsername(), MD5Utils.md5(model.getPassword()));
try {
subject.login(token);
} catch (Exception e) {
e.printStackTrace();
return LOGIN;
}
return HOME;
}
}
如果认证不成功,Shiro会抛出异常,此时我们在表现层需要处理异常。
(5)自定义Realm,配置bean并注入安全管理器
/**
* 自定义realm
* Title: BOSRealm <p>
* Description: <p>
* @author Tianyu Xiao
* @date 2018年10月23日
*/
public class BOSRealm extends AuthorizingRealm{
@Autowired
private IUserDao userDao;
/**
* 授权
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
return null;
}
/**
* 认证
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
return null;
}
}
配置spring:
<!-- 注册安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" >
<property name="realm" ref="bosRealm" />
</bean>
<!-- 注册realm -->
<bean id="bosRealm" class="com.itheima.bos.realm.BOSRealm"></bean>
3.Shiro的认证
登陆时认证的java代码在2.2(4)中已经完成,我们只需要在Realm中完成Shiro的认证即可。
编写Realm中的代码:
/**
* 认证
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken myToken = (UsernamePasswordToken) token;
String username = myToken.getUsername();
//根据用户名查询密码
User user = userDao.findUserByUsername(username);
if(user == null) {
//用户不存在
return null;//shiro 会抛出异常
}
//如果能查询到,再由框架比对数据库中查询到的密码和页面提交的密码是否一致
AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
return info;
}
4.Shiro的授权
4.1数据库准备工作
4.2在Realm中完成授权
/**
* 授权
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前登陆的用户对象
User user = (User) SecurityUtils.getSubject().getPrincipal();
//根据当前用户查询数据库,获取实际对应的权限
List<Function> functionList = null;
//如果是系统的内置账号(所有权限都可以访问)
if(user.getUsername().equals("admin")) {
functionList = functionDao.findAll();
}else {//是基本通用用户
functionList = functionDao.findFunctionByUserId(user.getId());
}
//为当前的用户授权
for (Function function : functionList) {
info.addStringPermission(function.getCode());
}
return info;
}
5.shiro框架提供的权限控制方式
(1)URL拦截权限控制(基于过滤器实现)
(2)方法注解权限控制(基于代理技术实现)
(3)页面标签权限控制(标签技术实现)