工具:jar包:https://download.csdn.net/download/ly_linyuan/10393067
1.先导入jar包
2.配置过滤器:web.xml:
<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整合shiro的配置文件spring-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" /> <!--加载管理器-->
<property name="loginUrl" value="/user/login" /> <!--没有登录的时候,跳转到这个页面-->
<property name="unauthorizedUrl" value="/user/nopermission" /> <!--当没有权限的时候,跳转到这个url-->
<property name="filterChainDefinitions">
<value>
/user/login = anon <!--可以不需要登录-->
/user/tologin = anon <!--可以不需要登录-->
/js/** = anon
<!-- /user/readName = authc, perms[/readName] perms 表示需要该权限才能访问的页面
/user/readData = authc, perms[/readData] -->
/user/* = authc <!-- authc 表示需要认证才能访问的页面 -->
</value>
</property>
</bean>
<!-- 自定义自定义权限认证Realm -->
<bean id="myShiroRealm" class="com.ly.shiro.MyShiroReaml">
<!-- businessManager 用来实现用户名密码的查询 -->
<property name="shiroService" ref="shiroService" />
<!-- 自定义密码加密算法 -->
<property name="credentialsMatcher" ref="passwordMatcher"/>
</bean>
<!-- 设置密码加密策略 md5hash -->
<bean id="passwordMatcher" class="com.ly.shiro.CustomCredentialsMatcher"/>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 注入realm -->
<property name="realm" ref="myShiroRealm"/>
</bean>
<!--声明一个Service 注入到自定义Realm-->
<bean id="shiroService" class="com.ly.service.impl.ShiroServiceImpl"/>
</beans>
4.编写密码比较器:
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
//密码比较的方法 token代表用户在界面输入的用户名和密码 info代表从数据库中得到加密数据
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
System.out.println("进入密码比较器中");
//1.向下转型
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
//2.将用户在界面输入的原始密码加密
Object pwd = MD5Change.GetMD5Code(new String(upToken.getPassword()));
//3.取出数据库中加密的密码
Object dbPwd = info.getCredentials();
return this.equals(pwd, dbPwd);
}
}
5.编写自定义realm域
public class MyShiroReaml extends AuthorizingRealm {
@Autowired
private UserRoleService userRoleService;
@Autowired
private RolePermissionService rolePermissionService;
@Autowired
private PermissionService permissionService;
@Autowired
private UserService userService;
private ShiroService shiroService;
public ShiroService getShiroService() {
return shiroService;
}
public void setShiroService(ShiroService shiroService) {
this.shiroService = shiroService;
}
//授权 当jsp页面出现Shiro标签时,就会执行授权方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
System.out.println("授权");
User user = (User) pc.fromRealm(this.getName()).iterator().next();//根据realm的名字去找对应的realm
//根据用户的id查询用户的用户角色关系表
List<UserRole> urlist = userRoleService.getByUserId(user.getId());
//新建一个集合保存用户所有权限名称
List<String> permissions = new ArrayList<String>();
//遍历用户角色关系表,得到用户角色权限表
for(UserRole ur : urlist){
//根据角色id查询角色权限关系表
List<RolePermission> rplist = rolePermissionService.getByRid(ur.getRoleid());
//遍历角色权限关系表,得到所有权限
for(RolePermission rp : rplist){
//根据角色权限关系表中的权限id查询到权限信息
Permission p = permissionService.getById(rp.getPermissionId());
permissions.add(p.getDescription());
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);//添加用户的模块(权限)
return info;
}
//认证 token 代表用户在界面输入的用户名和密码
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证");
//1.向下转型
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
//2.调用业务方法,实现根据用户名查询
User user = userService.getUserByUserName(upToken.getUsername());
if(user != null){
AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
System.out.println(info);
return info; //此处如果返回,就会立即进入到密码比较器
}
return null;//就会出现异常
}
}
6.登录controller代码:
@Controller
@RequestMapping("/user")
public class LoginController {
@Autowired
private ShiroService shiroService;
private Logger logger = Logger.getLogger(LoginController.class);
/**
* 跳转到登录页面
*/
@RequestMapping("/tologin")
public String tologin(){
return "login";
}
/**
* 验证登录
* @param username
* @param password
* @param session
* @return url
*/
@RequestMapping(value = "/login")
public String Login(String username, String password, HttpSession session, Model model){
if(username==null){
model.addAttribute("message", "账号不为空");
return "login";
}
//主体,当前状态为没有认证的状态“未认证”
Subject subject = SecurityUtils.getSubject();
// 登录后存放进shiro token
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
System.out.println(token);
User user;
//登录方法(认证是否通过)
//使用subject调用securityManager,安全管理器调用Realm
try {
//利用异常操作
//需要开始调用到Realm中
System.out.println("========================================");
System.out.println("1、进入认证方法");
subject.login(token);
user = (User)subject.getPrincipal();
session.setAttribute("user",subject);
model.addAttribute("message", "登录完成");
System.out.println("登录完成");
} catch (UnknownAccountException e) {
model.addAttribute("message", "账号密码不正确");
return "index";
}
return "test";
}
@RequestMapping("/check")
public String check(HttpSession session){
Subject subject=(Subject)session.getAttribute("user");
User user=(User)subject.getPrincipal();
System.out.println(user.toString());
return "permission";
}
@RequestMapping("/readName")
public String readName(HttpSession session){
return "name";
}
@RequestMapping("/readData")
public String readData(){
return "data";
}
@RequestMapping("/nopermission")
public String noPermission(){
return "error";
}
}
7.进入授权判断的页面: 当jsp页面出现Shiro标签时,就会执行授权方法
<%@ page language="java" isELIgnored="false" pageEncoding="UTF-8"%>
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<jsp:useBean id="now" class="java.util.Date" />
<html>
<head>
<title>Title</title>
</head>
<script src="/shirotest1/js/jquery1.42.min.js" type="text/javascript"></script>
<script src="/shirotest1/js/jquery-1.9.1.min.js"></script>
<body>
<shiro:hasPermission name="查看名单">
<a href="readName">查看名单</a>
</shiro:hasPermission>
<shiro:hasPermission name="查看数据">
<a href="readData">查看数据</a>
</shiro:hasPermission>
</body>
</html>
8.效果:
首页登录的用户有两个权限:查看名单,查看数据
再次登录另一个用户只有一个权限:查看名单