Java---Shiro框架

第一章   入门概述

1.1 什么是shiro

        Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。

 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架构(外部)

image-20200729114702566

从外部来看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架构(内部)

image-20200729114720578

  • 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登录认证

1. 创建数据库
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 DEFAULT
NULL ,
`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
2. 创建 web 项目并配置 SSM
完成 user 表的 dao 层和 service 层的书写
3. 创建 MyShiroRealm 继承 AuthorizingRealm
注意:使用 @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";
        }
    }
}

第三章 shirorememberMe功能

Shiro 提供了记住我( RememberMe )的功能,比如访问一些网站时,关闭了浏览器, 下次再打 开时还是能记住你是谁, 下次访问时无需再登录即可访问。
例如:当没有登录时,访问 /main 主页,会被拦截跳转到登录页面。当登录后是可以正常访
/main 的主页的;如果使用了记住我功能,会在浏览器写入 cookie ,关掉浏览器不需要登录即可 直接访问/main
基本流程
1. 首先在登录页面选中 RememberMe 然后登录成功;如果是浏览器登录,一般会 把
RememberMe Cookie 写到客户端并保存下来;
2. 关闭浏览器再重新打开;会发现浏览器还是记住你的;
3. 访问一般的网页服务器端,仍然知道你是谁,且能正常访问;
4. 但是,如果我们访问电商平台时,如果要查看我的订单或进行支付时,此时还 是需要再进行身份认
证的,以确保当前用户还是你。
1. spring.xml 中配置 cookie 的设置和 rememberMe 理器

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>
2. 页面上添加记住我勾选的复选框按钮,并设置 name 属性 rememberMe
<!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>
3. 修改 controller ,或者记住我功能是否勾选,认证时添加 记住我标记
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";
        }
    }
}
4. 测试 rerememberMe 功能
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>
2. spring.xml 配置文件中找到 shiro 过滤器,配置登出的 操作
<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角色授权认证

1. 在主页设计两个超链接,分别模拟查看用户管理和系统管
<!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>
2. 在控制器中使用 @RequiresRoles("roles") 注解来开启请 求的角色验证
   @RequiresRoles("user")
    @RequestMapping("/user")
    public String user(){
        System.out.println("用户管理");
        return "userList";
    }
    @RequiresRoles("admin")
    @RequestMapping("/system")
    public String system(){
        System.out.println("系统管理");
        return "system";
    }
3. springmvc.xml 中开启 shiro 的注解支持
由于 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>
4. 在主页访问两个超链接出现异常,提示操作没有对应的角
报错信息如下:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have role [admin]
5. 模拟进行角色认证,在自定义的 Realm 类的授权方法中, 手动给用户添加角色(后期使用数据库查询是否有角色), 然后查看能否正常访问。
@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权限授权认证

1. 在用户管理设计用户增删改查操作,分别模拟权限验证
<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>
2.shiro 配置参考如上
3. 在控制器中使用 @RequiresPermissions("permission") 注解来开启请求 的角色验证

    @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...";
    }
4. 在自定义的 Realm 类的授权方法中,手动给用户添加权限 (后期使用数据库查询是否有权限),然后查看能否正常访 问。
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;
    }

}
.......
5. 测试看能否访问用户管理页面
配置了 add 权限,点击用户添加可以正常访问;
点击用户删除则抛出异常如下:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have permission [user:delete]
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃汉堡的代码人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值