数据库关系:
需要用到的是function中的code属性
角色表
用户-角色关系表
1.在web包下的pom文件中配置shiro的支持包:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
2.在web.xml中配置shiro的过滤器,注意!!:shiroFilter需要放在shruts2的前面,我是放在struts2的前面,OpenSessionInViewFilter的后面
<!-- 配置spring框架提供搞得用户整合shiro框架的过滤器,放在struts2的前面-->
<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.在web包的resource包下配置spring-shiro.xm
(我起这个名字是因为我在web.xml中加载配置文件的方式是(classpath:spring-*.xml,需要注意的是,如果不起这个名字,需要chuagnjian 的shiro的xml文件在web.xml中能读到)
以下是spring-shiro.xml的代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd
">
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入安全管理器对象 -->
<property name="securityManager" ref="securityManager"></property>
<!-- 注入相关页面访问URL -->
<property name="loginUrl" value="/Login.jsp" />
<!-- 验证成功后要跳转的链接,一般不配置,跳转后的界面由action控制-->
<!-- <property name="successUrl" value="user/login" /> -->
<!--
通过unauthorizedUrl没有权限操作时跳转页面
解释:如果页面可以进入,但是页面上的按钮设置了权限,如果点击了且没有权限,会跳转到那个界面?
-->
<property name="unauthorizedUrl" value="/Login.jsp" />
<!-- 注入url拦截规则,这一个需要自己配置,具体配置,过两天吧数据库发过来,在配置,这里是重点 -->
<property name="filterChainDefinitions">
<value>
/css/*=anon
/img/*=anon
/layui/*=anon
/statics/css/*=anon
/statics/easyui/*=anon
/statics/images/*=anon
/statics/js/*=anon
/statics/json/*=anon
/index.jsp=anon
/login=anon
<!-- index/region_queryAllByPager=perms['region.query'] -->
/*=authc
</value>
</property>
</bean>
<!-- 注入安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="dmsRealm"></property>
</bean>
<!-- 注册realm,自己写的DMS文件的路径 -->
<bean id="dmsRealm" class="cn.lichenyang.dms.web.inteceptor.DMSRealm">
</bean>
<!-- 开启shiro框架注解支持 -->
<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
</bean>
<!-- 配置shiro框架提供的切面,用于创建代理对象 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" />
</beans>
4.以下是action中的代码
package cn.lichenyang.dms.web.action;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport;
import cn.lichenyang.dms.entity.TUser;
@Controller
@Scope("prototype")//非单例
@Namespace("/user")//命名空间
public class Test extends ActionSupport{
//form表单传过来的参数,通过用户对象来接收
private TUser user;
//页面使用/user/login请求该方法
@Action(value="login",results={
@Result(name="success",location="/WEB-INF/content/main.jsp"),
@Result(name="login",location="/Login.jsp")
})
public String login() {
//通过shiro进行登录验证
//从session中获取生成的验证码
String key = (String) ServletActionContext.getRequest().getSession().getAttribute("regcode");
//登录界面传过来的验证码
String checkcode = ServletActionContext.getRequest().getParameter("checkcode");
//校验验证码是否输入正确
if(StringUtils.isNotBlank(checkcode) && checkcode.equals(key)) {
//以上是我判断验证码是否正确的代码,直接看if条件中的内容就行了
//获取当前用户对象,状态为未认证
Subject subject = SecurityUtils.getSubject();
//创建用户对象,该token为Realm文件中的token,
//AuthenticationToken为UsernamePasswordToken的父类,传入用户账号和密码到realm文件中进行判断用户权限
AuthenticationToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
try {
//根据用户输入的账号密码进行登录验证,这一步只能通过subject的login方法进行验证
subject.login(token);
}catch(Exception e) {
e.printStackTrace();
//如果登录失败就返回登录界面
return LOGIN;
}
//如果登录成功,就得到当前对象,并把当前对象存到session中
TUser user = (TUser) subject.getPrincipal();
ServletActionContext.getRequest().getSession().setAttribute("userLogin",user );
return SUCCESS;
}else {
ServletActionContext.getRequest().setAttribute("msg", "验证码错误");
return LOGIN;
}
/*
//不采用shiro
//验证// session中验证码
String key = (String) ServletActionContext.getRequest().getSession().getAttribute("regcode");
if (key == null || !key.equals(ServletActionContext.getRequest().getParameter("checkcode"))) {
// 验证码无效
ServletActionContext.getRequest().setAttribute("msg", "验证码错误");
return LOGIN;
}
user = userService.login(user);
if(user != null) {
getSession().setAttribute("userLogin", user);
}else {
return LOGIN;
}
return SUCCESS;
*/
}
//=================================================================================================
//get,set方法
public TUser getUser() {
return user;
}
public void setUser(TUser user) {
this.user = user;
}
}
5.配置Realm文件
package cn.lichenyang.dms.web.inteceptor;
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import cn.lichenyang.dms.dao.IAuthFunctionDao;
import cn.lichenyang.dms.dao.ITUserDao;
import cn.lichenyang.dms.entity.AuthFunction;
import cn.lichenyang.dms.entity.TUser;
public class DMSRealm extends AuthorizingRealm{
@Autowired //创建用户接口对象(接口中有根据用户名查询当前用户方法)
private ITUserDao userDao;
@Autowired //这个是我的功能权限表中的内容,里面有我需要的功能权限的代码
private IAuthFunctionDao functionDao;
//认证方法
//在自定义的Realm中的doGetAuthenticationInfo方法中
//需要做的事:1.根据token进行查询然后检查对象是否为空以及其他自定义的条件,
// 2.最后封装成SimpleAuthenticationInfo返回就行了。
@Override
//Action中是:AuthenticationToken token = new UsernamePasswordToken();,所以()用AuthenticationToken类型
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("自定义realm中认证方法执行了。。。。。");
//第一步是从token中取到身份信息
UsernamePasswordToken passwordToken = (UsernamePasswordToken)token; //AuthenticationToken是UsernamePasswordToken的父类型
//获得页面输入的用户名
String username = passwordToken.getUsername();
//根据用户名查询数据库中的密码
TUser user = userDao.findUserByUserName(username);
if(user == null) {
return null; //页面输入的用户不存在(第一步完成)
}
//简单认证信息对象 //一般登录时进行权限验证,所以都是这3个参数
AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info;//(第二步完成)
}
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
//获取当前登录用户对象
TUser user = (TUser)SecurityUtils.getSubject().getPrincipal(); //自己随便选择哪一种
//TUser user = (TUser)principals.getPrimaryPrincipal(); //以上2种获取对象的方式都行
//根据当前登录用户查询数据库,获取实际对应的权限
List<AuthFunction> list = null; //创建一个权限功能的集合(因为我的功能不)
if(user.getUsername().equals("admin")) { //判断用户是否为超级管理员,如果是,就可以执行所有权限,如果不行只能执行自己的权限
//超级管理员内容之用户,查询所有权限数据
list=functionDao.findAll(); //可以执行所有权限
}else {
list=functionDao.queryById(user.getUserId());//只能执行自己的权限
}
//以下3步是创建权限
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
for (AuthFunction Function : list) {
info.addStringPermission(Function.getCode()); //将权限放到shiro中
}
return info; //返回这个权限
}
}
6.接下来根据所用的角色进行登录就行了