第一章 入门概述
1.1 什么是shiro
Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。
-
下载地址
- 官网:Apache Shiro | Simple. Java. Security.
- github:GitHub - apache/shiro: Apache Shiro
1.2 为什么要用shiro
自 2003 年以来,框架格局发生了相当大的变化,因此今天仍然有很多系统在使用Shiro。这与 Shiro 的特性密不可分。
易于使用:使用 Shiro 构建系统安全框架非常简单。就算第一次接触也可以快速掌握。
全面:Shiro 包含系统安全框架需要的功能,满足安全需求的“一站式服务”。
灵活:Shiro 可以在任何应用程序环境中工作。虽然它可以在 Web、EJB 和 IOC 环境中工作,但不需要依赖它们。Shiro 也没有强制要求任何规范,甚至没有很多依赖项。
强力支持 Web:Shiro 具有出色的 Web 应用程序支持,可以基于应用程序 URL 和Web 协议(例如 REST)创建灵活的安全策略,同时还提供一组 JSP 库来控制页面输出。
兼容性强:Shiro 的设计模式使其易于与其他框架和应用程序集成。Shiro 与Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 等框架无缝集成。
1.3 Shiro 与 SpringSecurity 的对比
1、Spring Security 基于 Spring 开发,项目若使用 Spring 作为基础,配合 SpringSecurity 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
3、Spring Security 社区资源相对比 Shiro 更加丰富;
4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行Spring Security 依赖Spring 容器;
6、shiro 不仅仅可以使用在 web 中,它可以工作在任何应用环境中。在集群会话时 Shiro最重要的一个好处或许就是它的会话是独立于容器的。
1.4 有哪些功能?
(1)Authentication:身份认证/登录,验证用户是不是拥有相应的身份。
(2)Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限。
(3)Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境,也可以是Web 环境的。
(4)Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储。
(5)Web Support:Web 支持,可以非常容易的集成到Web 环境。
(6)Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率。
(7)Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去。
(8)Testing:提供测试支持。
(9)“Run As”:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。
(10)Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
1.5 Shiro架构(外部)
从外部来看Shiro,即从应用程序角度的来观察如何使用Shiro完成工作
Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API 核心就是Subject。Subject 代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;与Subject 的所有交互都会委托给SecurityManager;Subject 其实是一个门面,SecurityManager才是实际的执行者
SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且其管理着所有Subject;可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC中DispatcherServlet的角色
Realm:Shiro从Realm 获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm 得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm 看成DataSource。
1.6 Shiro架构(内部)
- Subject:任何可以与应用交互的“用户”。
- SecurityManager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject、且负责进行认证、授权、会话及缓存的管理。
- Authenticator:负责Subject 认证,是一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
- Authorizer:授权器、即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能。
- Realm:可以有1 个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC 实现,也可以是内存实现等等;由用户提供;所以一般在应用中都需要实现自己的Realm。
- SessionManager:管理Session 生命周期的组件;而Shiro并不仅仅可以用在Web 环境,也可以用在如普通的JavaSE环境。
- CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能。
- Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密。
第二章 shiro登录认证
SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0 ;-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`uid` int ( 11 ) NOT NULL AUTO_INCREMENT,`uname` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,`pwd` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,`sex` varchar ( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,`address` varchar ( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULTNULL ,`state` int ( 2 ) DEFAULT NULL ,`salt` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,PRIMARY KEY (`uid`) USING BTREE,UNIQUE INDEX `uname`(`uname`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE =utf8_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES ( 1 , 'admin' , '727d8b2b4c59366d7ace58d4eda4cfee' , ' 女 ' ,' 河南洛阳 ' , 1 , '9C2AB20283F9450389330033D64686DD' );INSERT INTO `user` VALUES ( 2 , 'zs' , '83f12ba7c4357b87167e240a22c15248' , ' 男 ' , ' 河南郑州 ' , 1 , '262F995823C94D1CAE7596B47E8AB657' );select * from user
完成 user 表的 dao 层和 service 层的书写
注意:使用 @Component 注解交给 spring 管理
package com.chen.shiro;
import com.chen.bean.User;
import com.chen.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
4.在spring.xml中配置shiro管理器和自定义的Realm
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* token 里面是客户端发来的信息(包含输入的用户名 和 密码)
* 自定义Realm,通过mybatis查询数据库的密码和盐值,让shiro进行身份验证
*/
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
IUserService userService;
//shiro 进行授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
principals) {
return null;
}
//shiro 进行认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken
token) throws AuthenticationException {
//token 是主体传过来的身份令牌
//1 获取用户身份信息
String uname = token.getPrincipal().toString();
//2 调用业务层获取用户信息(数据库中)
User user = userService.findByUname(uname);
//3 判断并将数据完成封装
if(user!=null){
AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
token.getPrincipal(), //令牌身份信息对象
user.getPwd(), //用户数据库的密码
ByteSource.Util.bytes(user.getSalt().getBytes()), //加密时的
盐值
uname // 用户名
);
return authenticationInfo;
}
return null;
}
}
4.在spring.xml中配置shiro管理器和自定义的Realm
<!--=================shiro相关配置====================-->
<!--配置shiro进行校验时的加密规则-->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--加密规则-->
<property name="hashAlgorithmName" value="MD5" />
<!--是否加盐-->
<property name="hashSalted" value="true" />
<!--是否增加哈希算法进行散列-->
<!-- <property name="hashIterations" value="1024" />-->
</bean>
<!--配置自定义Realm-->
<bean id="myRealm" class="com.chen.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!--配置安全管理器,使用自定义的Realm-->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--配置自定义的Realm-->
<property name="realm" ref="myRealm" />
</bean>
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置拦截后我们的登录请求地址 -->
<property name="loginUrl" value="/loginUI"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 权限配置
anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
me;
perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
user:登录用户才可以访问,包含remember me; logout:退出
-->
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>
</bean>
权限配置anon :任何人都可以访问;authc :必须是登录之后才能进行访问,不包括 remember me ;perms :指定过滤规则,可以自己拓展权限配置;roles :配置角色;user :登录用户才可以访问,包含 remember me ;logout :退出
5.web.xml中配置shiro的过滤器
<!-- shiro配置 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filterclass>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.在controller中进行shiro认证
package com.chen.controller;
import com.chen.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/login")
public String login(String uname, String pwd, HttpSession session) {
System.out.println(uname+"------------------");
//1 获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//2 封装请求数据到 token 对象中
AuthenticationToken token = new UsernamePasswordToken(uname, pwd);
//3 调用 login 方法进行登录认证
try {
//5.验证主体是否能够登录
subject.login(token);
session.setAttribute("user", token.getPrincipal().toString());
return "main";
} catch (UnknownAccountException e) {
System.out.println("用户名不存在!");
return "login";
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误!");
return "login";
} catch (AuthenticationException e) {
System.out.println("认证失败,不知道出了什么问题");
return "login";
}
}
}
第三章 shiro的rememberMe功能
Shiro 提供了记住我( RememberMe )的功能,比如访问一些网站时,关闭了浏览器, 下次再打 开时还是能记住你是谁, 下次访问时无需再登录即可访问。例如:当没有登录时,访问 /main 主页,会被拦截跳转到登录页面。当登录后是可以正常访问 /main 的主页的;如果使用了记住我功能,会在浏览器写入 cookie ,关掉浏览器不需要登录即可 直接访问/main 。
1.配置记住我功能的cookie设置;
2. 配置记住我功能的管理器;3. 在安全管理器中引用记住我功能的管理器;4. 在过滤器中 shiroFilter 配置 rememberMe 的过滤配置( /**=user )
<!--=================shiro相关配置====================-->
<!--配置shiro进行校验时的加密规则-->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--加密规则-->
<property name="hashAlgorithmName" value="MD5" />
<!--是否加盐-->
<property name="hashSalted" value="true" />
<!--是否增加哈希算法进行散列-->
<!-- <property name="hashIterations" value="1024" />-->
</bean>
<!--配置自定义Realm-->
<bean id="myRealm" class="com.chen.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!--=================记住我功能相关配置====================-->
<!--记住我功能的cookie设置-->
<bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--设置cookie的属性名-->
<property name="name" value="rememberMe" />
<!--设置cookie存在根目录,可在同一应用服务器内共享-->
<property name="path" value="/" />
<!--通过JavaScript脚本将无法读取到Cookie信息,这样能有效的防止XSS攻击,让网站应用更
加安全-->
<property name="httpOnly" value="true" />
<!--设置cookie的失效时间为30天-->
<property name="maxAge" value="2592000" />
</bean>
<!--记住我功能的管理器配置-->
<bean id="rememberMeManager"
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!--引用cookie设置-->
<property name="cookie" ref="simpleCookie" />
<!--默认AES算法,设置cookie的加密算法,采用的是base64的加密-->
<property name="cipherKey" value="#
{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
</bean>
<!--配置安全管理器,使用自定义的Realm-->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--配置自定义的Realm-->
<property name="realm" ref="myRealm" />
<!--====引用rememberMe功能管理器====================-->
<property name="rememberMeManager" ref="rememberMeManager" />
</bean>
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置拦截后我们的登录请求地址 -->
<property name="loginUrl" value="/loginUI"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 权限配置 -->
<!-- 权限配置
anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
me;
perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
user:登录用户才可以访问,包含remember me; logout:退出
-->
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>
</bean>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<div id="content">
<form class="form-horizontal" action="/login" method="post">
<div class="form-group">
<label for="uname" class="col-sm-2 control-label">帐号</label>
<div class="col-sm-10">
<input type="text" name="uname" class="form-control" id="uname"
placeholder="帐号">
</div>
</div>
<div class="form-group">
<label for="pwd" class="col-sm-2 control-label">密码</label>
<div class="col-sm-10">
<input type="password" name="pwd" class="form-control" id="pwd"
placeholder="密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" name="rerememberMe"> 记住我
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" id="login" class="btn btn-primary">登录
</button>
<a href="/indexUI">去注册</a>
</div>
</div>
</form>
</div>
</body>
</html>
1. 配置 boolean 类型的请求参数 rerememberMe ,并设置默认值是 false ;2. 在封装 token 时,加入 rerememberMe 标记;
package com.chen.controller;
import com.chen.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/login")
public String login(String uname, String pwd, @RequestParam(defaultValue = "false") boolean rerememberMe, HttpSession session) {
System.out.println(uname+"------------------");
//1 获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//2 封装请求数据到 token 对象中
AuthenticationToken token = new UsernamePasswordToken(uname, pwd,rerememberMe);
//3 调用 login 方法进行登录认证
try {
//5.验证主体是否能够登录
subject.login(token);
session.setAttribute("user", token.getPrincipal().toString());
return "main";
} catch (UnknownAccountException e) {
System.out.println("用户名不存在!");
return "login";
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误!");
return "login";
} catch (AuthenticationException e) {
System.out.println("认证失败,不知道出了什么问题");
return "login";
}
}
}
1. 不登录直接访问主页 /main , shiro 会拦截去到登录页;登录后可以正常访问主页 /main ;2. 登录时不勾选记住我,关闭浏览器访问主页 /main 还会拦截到登录页;3. 登录时勾选记住我,关闭浏览器访问主页 /main 可以正常访问;
第四章 shiro的登出
1.在主页设置退出登录的链接
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>主页</title>
<body>
<img src="/img/index.jpg">
<a href="/logout">退出登录</a>
</body>
</html>
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/logout=logout
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>
第六章 shiro角色授权认证
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
</head>
<body>
<h2>内容页</h2>
<a href="/loginOut">退出登录</a>
<hr>
<ul>
<li><a href="/user">用户管理</a></li>
<li><a href="/system">系统管理</a></li>
</ul>
</body>
</html>
@RequiresRoles("user")
@RequestMapping("/user")
public String user(){
System.out.println("用户管理");
return "userList";
}
@RequiresRoles("admin")
@RequestMapping("/system")
public String system(){
System.out.println("系统管理");
return "system";
}
由于 shiro 注解是在 controller 中配置,所以需要在 springmvc.xml 中配置 shiro 的注解支持;1. 配置 shiro bean 生命周期处理器2. 配置自动创建代理;3. 开启 shiro 注解的支持
<!--配置shiro bean生命周期处理器-->
<bean id="lifecycleBeanPostProcessor"
class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!--配置自动创建代理-->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<!-- 开启shiro注解的支持 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
报错信息如下:org.springframework.web.util.NestedServletException: Request processingfailed; nested exception is org.apache.shiro.authz.UnauthorizedException:Subject does not have role [admin]
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
principalCollection) {
System.out.println("授权方法被执行==============");
//创建角色和权限对象
SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
//模拟添加角色
authorizationInfo.addRole("user");
//返回权限
return authorizationInfo;
}
...
第七章 shiro权限授权认证
<body>
<ul>
<li><a href="/user/add">添加用户</a></li>
<li><a href="/user/delete">删除用户</a></li>
<li><a href="/user/find">查看用户</a></li>
<li><a href="/user/revise">修改用户</a></li>
</ul>
</body>
@RequiresPermissions("user:add")
@RequestMapping("/user/add")
@ResponseBody
public String add(){
System.out.println("用户添加操作");
return "action user add...";
}
@RequiresPermissions("user:add")
@RequestMapping("/user/delete")
@ResponseBody
public String delete(){
System.out.println("用户删除操作");
return "action user delete...";
}
@RequiresPermissions("user:find")
@RequestMapping("/user/find")
@ResponseBody
public String find(){
System.out.println("用户查看操作");
return "action user find...";
}
@RequiresPermissions("user:revise")
@RequestMapping("/user/revise")
@ResponseBody
public String revise(){
System.out.println("用户修改操作");
return "action user revise...";
}
package com.chen.shior;
import com.chen.bean.User;
import com.chen.service.UserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 自定义Realm,通过mybatis查询教据库密码和盐值,让shiro进行身份验证
*/
@Component
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//shiro 进行授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("授权方法被执行==============");
//1.创建角色和权限对象
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//2.1 获取用户登录
String uname = principalCollection.getPrimaryPrincipal().toString();
System.out.println("当前登录用户为:"+uname);
if (uname.equals("admin")){
//正常查询用户的角色(数据库使用set) 现在模拟赋予角色
String role ="admin";
authorizationInfo.addRole(role);
authorizationInfo.addRole("user");
//授予权限正常查询用户的权限,现在模拟赋予权限
authorizationInfo.addStringPermission("user:add");
authorizationInfo.addStringPermission("user:delete");
authorizationInfo.addStringPermission("user:find");
authorizationInfo.addStringPermission("user:revise");
}else {
authorizationInfo.addRole("user");
authorizationInfo.addStringPermission("user:add");
authorizationInfo.addStringPermission("user:find");
}
//返回权限
return authorizationInfo;
}
}
.......
配置了 add 权限,点击用户添加可以正常访问;点击用户删除则抛出异常如下:org.springframework.web.util.NestedServletException: Request processingfailed; nested exception is org.apache.shiro.authz.UnauthorizedException:Subject does not have permission [user:delete]