(视频:哔哩哔哩-编程不良人)

一:权限的管理(1~3)

1. 什么是权限管理:

3. 什么是身份认证:

5. 什么是授权:

二:什么是 Shiro(4~4)

1. 官网:https://shiro.apache.org/
2. 英文文档:https://shiro.apache.org/reference.html
3. 中文文档:http://greycode.github.io/shiro/doc/reference.html

三:Shiro 的核心架构(4~4)

1. Shiro 核心架构图:(视频p4:详解)

3. 模块解释说明:

四:Shiro中的认证(5~5)

1. 认证:

2. Shiro 中认证的关键对象:

3. 认证大体流程:

4. 认证的开发:
1)引入 shiro 依赖:

        <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.5.3</version></dependency>
        <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.8.0</version></dependency>

’ 2)创建:shiro.ini 文件

[users]
zhangsan=123456
lisi=123456
wangwu=123456
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5

’ 3)完成认证:

    public static void main(String[] args) {//1:创建安全管理器DefaultSecurityManager securityManager = new DefaultSecurityManager();//2:给安全管理器设置 RealmIniRealm iniRealm = new IniRealm("classpath:shiro.ini");securityManager.setRealm(iniRealm);//3:给全局工具类,设置全局安全管理器SecurityUtils.setSecurityManager(securityManager);//4:获取主体对象Subject subject = SecurityUtils.getSubject();//5:创建安全令牌UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("zhangsan", "123456");usernamePasswordToken.setRememberMe(true);try {subject.login(usernamePasswordToken);} catch (UnknownAccountException e) {System.out.println("账户错误:" + e);} catch (IncorrectCredentialsException e) {System.out.println("密码错误:" + e);}boolean authenticated = subject.isAuthenticated();System.out.println("用户是否登陆:" + authenticated);subject.logout();boolean authenticated2 = subject.isAuthenticated();System.out.println("用户是否登陆:" + authenticated2);}

5. 认证流程源码查看:
0)最终执行用户比较:SimpleAccountRealm。doGetAuthenticationInfo() 方法中完成用户名校验
0)最终密码校验是在 AuthenticatingRealm 中,assertCredentialsMatch()。
1)完成用户名校验:(SimpleAccountRealm)(方法中实现,可换成自己去读取数据库)

2)完成密码校验:(AuthenticatingRealm)



3)Realm 继承关系图:(自定义 Realm 继承 AuthorizingRealm 类)


4)以 SimpleAccountRealm 为例:

5)总结:

  • 1.AuthenticatingRealm --> 认证Realm–>doGetAuthenticationInfo()
  • 2.AuthorizingRealm --> 授权Realm --> getAuthorizationInfo()
  • 3.如果需要自定义 Realm,参考 SimpleAccountRealm 继承 AuthorizingRealm,才可覆盖认证、授权,两个方法。

6. 自定义 Realm 实现:( securityManager.setRealm(new MyRealm()); )

@Component
public class MyRealm extends AuthorizingRealm {@Autowiredprivate BlogUserService blogUserService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String principal = (String) token.getPrincipal();System.out.println("username:" + principal);//根据用户名查询数据库BlogUserEntity blogUserDB = blogUserService.getBlogUserByUsername(principal);if (!ObjectUtils.isEmpty(blogUserDB)) {//用户名、盐值、密码、//当前realm名称return new SimpleAuthenticationInfo(blogUserDB.getUsername(), "", blogUserDB.getPassword());
//          return new SimpleAuthenticationInfo(blogUserDB.getUsername(), blogUserDB.getPassword(), this.getName());}return null;}}
    public static void main(String[] args) {SpringApplication.run(MyShiroDemo01Application.class, args);final Md5Hash md5Hash = new Md5Hash("123", "salt",1024);String resultStr = md5Hash.toHex();System.out.println(resultStr);// 1:创建 securityManagerDefaultSecurityManager securityManager = new DefaultSecurityManager();// 2:设置自定义 RealmsecurityManager.setRealm(new MyRealm());// 3:通过安全工具类,设置安全管理器SecurityUtils.setSecurityManager(securityManager);// 4:通过安全工具类,获取 subject 主体Subject subject = SecurityUtils.getSubject();// 5:创建 tokenUsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("张三", "123");usernamePasswordToken.setRememberMe(true);// 6:登陆操作try {subject.login(usernamePasswordToken);} catch (UnknownAccountException e) {System.out.println("用户名出错");} catch (IncorrectCredentialsException e2) {System.out.println("密码出错");}System.out.println(subject.isAuthenticated());}

五:MD5 和 Salt 的简介和执行流程说明(6~9)

1. MD5 算法简介:
1)作用:一般用来加密、签名。
2)特点:MD5 算法不可逆,内容相同,无论执行多少次,结果始终一样。
3)结果:始终是一个 16进制,32位长度的字符串。
2. 使用:

     // 1:加盐final Md5Hash md5Hash = new Md5Hash("123", "salt");String resultStr = md5Hash.toHex();System.out.println(resultStr);// 2:加盐加散列final Md5Hash md5Hash = new Md5Hash("123", "salt", 1024);String resultStr = md5Hash.toHex();System.out.println(resultStr);

3. 实现:(使用自定义 Realm,加入:md5、salt、hash散列)
’ 0)凭证匹配器继承关系:在自定义 Realm 中,进行设定凭证匹配器。

’ 1)md5:

    public static void main(String[] args) {DefaultSecurityManager securityManager = new DefaultSecurityManager();// 1、设置 Realm 为 Hash 凭证匹配器MyMd5Realm myMd5Realm = new MyMd5Realm();//     2.1、自定义 Realm 设置,自定义凭证匹配器HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();//  2.2、加密算法、散列次数matcher.setHashAlgorithmName("md5");matcher.setHashIterations(1024);//     2.3、给自定义 Realm,设置自定义凭证匹配器myMd5Realm.setCredentialsMatcher(matcher);// 3:给安全管理器设置 RealmsecurityManager.setRealm(myMd5Realm);// 4:给全局工具类,设置安全管理器SecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();// 5、创建 tokenUsernamePasswordToken token = new UsernamePasswordToken("张三", "123456");token.setRememberMe(true);try {subject.login(token);System.out.println(subject.isAuthenticated());} catch (UnknownAccountException e) {System.out.println("用户名错误");} catch (IncorrectCredentialsException e) {System.out.println("密码错误");}}
public class MyMd5Realm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String principal = (String) token.getPrincipal();System.out.println(principal);if ("张三".equals(principal)) {return new SimpleAuthenticationInfo("张三", "e10adc3949ba59abbe56e057f20f883e",ByteSource.Util.bytes("sss"),this.getName());}return null;}}

’ 2)md5 + 加随机盐值:

 /*** 参数:数据库用户名、数据库加密后的密码,*        注册时的随机盐值、realm的名字;* * 只需要加一次盐值,shiro会自动把用户输入密码加盐值。*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String principal = (String) token.getPrincipal();System.out.println(principal);if ("张三".equals(principal)) {// 用户名、密码,都为数据库中存储的加密后的return new SimpleAuthenticationInfo("张三","5194528bd63abca4bf9d09885bb425b7",ByteSource.Util.bytes("sss"),this.getName());}return null;}

‘ 3)md5 + 加随机盐值::(1024次)(除了上面加盐的地方,Realm声明散列次数)

        DefaultSecurityManager securityManager = new DefaultSecurityManager();//设置 Realm 为 Hash 凭证匹配器MyMd5Realm myMd5Realm = new MyMd5Realm();//设置hash算法HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();matcher.setHashAlgorithmName("md5");matcher.setHashIterations(1024);// assertCredentialsMatch()方法,会获取默认凭证匹配器,// 所以,要先设置自定义凭证匹配器,放入hash算法规则myMd5Realm.setCredentialsMatcher(matcher);//设置RealmsecurityManager.setRealm(myMd5Realm);SecurityUtils.setSecurityManager(securityManager);

六:授权(10~11)

1. 授权:

3. 关键对象:

5. 授权流程:

7. 授权方式:

9. 权限字符串详解:

10. shiro 中授权编码实现方式
’ 1)编程式:

’ 2)注解式:

’ 3)标签式:

12. 角色管理:实际运用:
’ 1)验证完身份,给主体授权操作:

public class MyMd5Realm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//进行给当前主体授权HashSet<String> hashSet = new HashSet<>();hashSet.add("admin");hashSet.add("user");SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(hashSet);return simpleAuthorizationInfo;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {return null;}
}

’ 2)验证主体是否有某种角色:(3种方法)

        //验证身份通过后,进行授权if (subject.isAuthenticated()) {//1.判断主体是否具有某个权限System.out.println(subject.hasRole("admin"));System.out.println(subject.hasRole("user"));//2.判断主体是否同时满足这两个条件System.out.println(subject.hasAllRoles(Arrays.asList("admin", "user")));//3.判断主体是否具有某个权限boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "user"));for (boolean b : booleans) {System.out.println(b);}}

14.(权限)基于权限字符串的访问控制:实际操作:
’ 1):(资源标识符:操作:资源类型)

public class MyMd5Realm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String primaryPrincipal = (String) principals.getPrimaryPrincipal();//可根据用户名,获取数据库的 角色信息、权限信息。//将数据库查询到 角色 信息,赋值给权限对象HashSet<String> hashSet = new HashSet<>();hashSet.add("admin");hashSet.add("user");SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(hashSet);//将数据库查询到 权限 信息,赋值给权限对象simpleAuthorizationInfo.addStringPermission("user:*:001");return simpleAuthorizationInfo;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {return null;}}

’ 2)判断是否有权限:(权限验证)

        //验证身份通过后,进行验证if (subject.isAuthenticated()) {//1.基于权限字符串访问控制System.out.println(subject.isPermitted("user:*:*"));//falseSystem.out.println(subject.isPermitted("user:*:001"));//trueSystem.out.println(subject.isPermitted("user:update:001"));//true//2.同时具有哪些权限boolean permittedAll = subject.isPermittedAll("user:*:002", "user:*:001");System.out.println(permittedAll);//false//3.分别具有哪些权限boolean[] permitted = subject.isPermitted("user:*:002", "user:*:001");System.out.println(Arrays.toString(permitted));//[false, true]}

七:SpringBoot 整合 shiro 之 环境搭建(12~14)

1. 认证授权流程:

2. 创建springboot应用:
’ 1)整合 jsp 依赖:

        <dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency>

’ 2)yml 配置:

server:port: 8080
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://114.215.173.88:3306/shiro-test-01username: rootpassword: 123456mvc:view:prefix: /suffix: .jspmybatis:type-aliases-package: com.shiro.myshirodemo02jsp.entitymapper-locations: classpath:mapper/*.xml

’ 3)访问:http://localhost:8080/index.jsp
如果启动失败,需设置工作目录:

3. 配置 Shiro 相关:
’ 1)引入 springboot 整合 shiro 依赖:

        <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-starter</artifactId><version>1.5.3</version></dependency>

’ 2)ShiroConfig:(3个 Bean 配置)

@Configuration
public class ShiroConfig {// 1:创建 shiro filter,//负责拦截所有请求@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// 给 filter 设置 安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);// 设置拦截路径HashMap<String, String> filterMap = new HashMap<>();filterMap.put("/index.jsp", "authc");//authc:标识请求此资源需要认证和授权shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);// 设置默认的认证界面路径shiroFilterFactoryBean.setLoginUrl("/login.jsp");        return shiroFilterFactoryBean;}// 2:创建 安全管理器@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();defaultWebSecurityManager.setRealm(realm);return defaultWebSecurityManager;}// 3:创建 realm@Beanpublic Realm getRealm() {return new CustomerRealm();}}

’ 3)MyRealm:

//自定义Realm
public class CustomerRealm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// 后面补充return null;}
}

’ 4)请求测试:(注:如使用 thymleaf,需要控制器跳转到页面)
访问:http://localhost:8080/index.jsp,跳转到登陆页面

八:整合 Shiro 之 认证和退出(15~15)

1. shiro 提供的 常见 过滤器:

2. 写登陆页面:

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>登陆页面</title>
</head>
<body>
<h1>我的登陆页面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">账号:<input type="text" name="username"><br>密码:<input type="text" name="password"><br><input type="submit" value="登陆">
</form>
</body>
</html>

’ 4)controller:

@Controller
@RequestMapping(value = "/user")
public class ShiroController {@PostMapping(value = "/login")public String login(String username, String password) {System.out.println(username + ":" + password);Subject subject = SecurityUtils.getSubject();UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);try {subject.login(usernamePasswordToken);return "redirect:/index.jsp";} catch (UnknownAccountException e) {System.out.println("账号错误");} catch (IncorrectCredentialsException e) {System.out.println("密码错误");}return "redirect:/login.jsp";}
}

’ 5)编写认证管理器:

//自定义Realm
public class MyRealm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();BlogUserEntity blogUserDB = shiroUserService.getUserByUsername(username);if (blogUserDB != null) {return new SimpleAuthenticationInfo(blogUserDB.getUsername(),blogUserDB.getPassword(),this.getName());}return null;}
}

’ 6)退出登陆:
1.index.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>菜单页面</title>
</head>
<body>
<h1>菜单页面</h1>
<ul><li><a href="">用户管理</a></li><li><a href="">订单管理</a></li><li><a href="">商品管理</a></li><li><a href="">物流管理</a></li>
</ul>
<h1><a href="${pageContext.request.contextPath}/user/logout">退出登陆</a></h1>
</body>

’ 2.controller:

    @GetMapping(value = "/logout")public String logout() {// 通过安全工具类,获取主体信息并登出Subject subject = SecurityUtils.getSubject();if (subject != null && subject.isAuthenticated()) {subject.logout();}return "redirect:/login.jsp";}

九:认证 + salt + 散列(16~17)

1. 创建数据库:

CREATE TABLE `blog_user` (`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`username` varchar(255) NOT NULL DEFAULT '' COMMENT '用户名',`password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码',`salt` varchar(255) NOT NULL DEFAULT '' COMMENT '盐值',PRIMARY KEY (`id`)
);


3. mybatis 整合:
’ 1)相关依赖:

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version>
</dependency>

’ 2)相关配置:

spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://114.215.173.88:3306/testdbusername: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSourcemybatis:type-aliases-package: com.shiro.myshirodemo02jsp.entitymapper-locations: classpath:mybatis/mapper/*.xml

’ 3)mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.shiro.myshirodemo02jsp.dao.ShiroUserDao"><insert id="addUser">insert into blog_user (username, password, salt)values (#{username}, #{password}, #{salt})</insert><select id="getUserByUsername" resultType="com.example.myshirodemo02testjsp.entity.BlogUserEntity">select *from blog_userwhere username = #{principal}</select>
</mapper>

5. 用户注册:
’ 1)jsp:

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>登陆页面</title>
</head>
<body>
<h1>我的登陆页面</h1>
<form action="${pageContext.request.contextPath}/user/register" method="post"><input type="text" name="username"><br><input type="text" name="password"><br><input type="submit" value="用户注册"><br>
</form>
</body>
</html>

’ 2)controller:

@Controller
@RequestMapping(value = "/user")
public class ShiroController {@Autowiredprivate ShiroUserService shiroUserService;@PostMapping(value = "/register")public String register(String username, String password) {System.out.println(username + ":" + password);Md5Hash newPassword = new Md5Hash(password, "salt", 1024);shiroUserService.addUser(username, newPassword.toHex(), "salt");return "redirect:/user/login.jsp";}}

7. 用户登陆:(md5 + 随机盐 认证)
’ 1)修改 Realm 认证方式:

@Configuration
public class ShiroConfig {@Beanpublic Realm getRealm() {MyRealm myRealm = new MyRealm();//修改凭证校验匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();credentialsMatcher.setHashAlgorithmName("md5");credentialsMatcher.setHashIterations(1024);myRealm.setCredentialsMatcher(credentialsMatcher);return myRealm;}
}

’ 2)修改 :

    @Autowiredprivate ShiroUserService shiroUserService;@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();BlogUserEntity blogUserDB = shiroUserService.getUserByUsername(username);if (blogUserDB != null) {return new SimpleAuthenticationInfo(blogUserDB.getUsername(),blogUserDB.getPassword(),ByteSource.Util.bytes("salt"),this.getName());}return null;}

’ 3)customerRealm 中,无法获取容器中 service 实例,解决方案。
i:增加工具类,用于获取容器中对象实例:

@Component
public class ApplicationContextUtils implements ApplicationContextAware {public static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {context = applicationContext;}/*** 根据 bean 名字,获取工厂中指定的 bean 对象*/public static Object getBean(String beanName) {return context.getBean(beanName);}}

ii:修改 注入 service 方法:

    @Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();// 获取容器中对象实例ShiroUserService shiroUserService = (ShiroUserService) ApplicationContextUtils.getBean("shiroUserServiceImpl");BlogUserEntity blogUserDB = shiroUserService.getUserByUsername(username);if (blogUserDB != null) {return new SimpleAuthenticationInfo(blogUserDB.getUsername(),blogUserDB.getPassword(),ByteSource.Util.bytes("salt"),this.getName());}return null;}

十:整合 shiro 之授权基本使用:(18~20)

1. 授权管理器编码:(基于角色权限管理)

@Component
public class MyRealm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String primaryPrincipal = (String) principals.getPrimaryPrincipal();//根据主体,获取角色信息,权限信息if ("zhangsan".equals(primaryPrincipal)) {SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();simpleAuthorizationInfo.addRole("admin");return simpleAuthorizationInfo;}return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {return null;}
}

3. index.jsp 页面控制:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>菜单页面</title>
</head>
<body>
<h1>菜单页面</h1>
<ul><shiro:hasAnyRoles name="admin,user">admin、user角色可以看到<li><a href="">用户管理</a></li></shiro:hasAnyRoles><shiro:hasRole name="user">admin 角色可以看到<li><a href="">订单管理</a></li><li><a href="">商品管理</a></li><li><a href="">物流管理</a></li></shiro:hasRole><li><a href="${pageContext.request.contextPath}/user/logout">退出登陆</a></li>
</ul>
</body>
</html>

5. 效果:

7. 基于权限字符串做权限管理:
’ 1)授权管理编码:

@Component
public class MyRealm extends AuthorizingRealm {@Autowiredprivate ShiroUserService shiroUserService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String primaryPrincipal = (String) principals.getPrimaryPrincipal();//根据主体,获取角色信息,权限信息if ("zhangsan".equals(primaryPrincipal)) {SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();simpleAuthorizationInfo.addRole("admin");//设置权限字符串simpleAuthorizationInfo.addStringPermission("user:*:*");return simpleAuthorizationInfo;}return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {return null;}
}

’ 2)index.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>菜单页面</title>
</head>
<body>
<h1>菜单页面</h1>
<ul><shiro:hasAnyRoles name="admin,user">admin、user角色可以看到<li><a href="">用户管理</a><shiro:hasPermission name="user:add:*"><ul><a href="">增加用户</a></ul></shiro:hasPermission><shiro:hasPermission name="user:delete:*"><ul><a href="">删除用户</a></ul></shiro:hasPermission><shiro:hasPermission name="user:update:*"><ul><a href="">修改用户</a></ul></shiro:hasPermission><shiro:hasPermission name="user:find:*"><ul><a href="">查询用户</a></ul></shiro:hasPermission></li></shiro:hasAnyRoles><li><a href="${pageContext.request.contextPath}/user/logout">退出登陆</a></li>
</ul>
</body>
</html>

’ 3)测试效果:

9. controller 两种实现:
’ 1)编码式:

@RestController
@RequestMapping(value = "/user")
public class ShiroUserController {@RequestMapping(value = "/addUser")public String add() {Subject subject = SecurityUtils.getSubject();if (subject.hasRole("admin")) {System.out.println("新增成功");} else {System.out.println("没有权限");}return null;}}

’ 2)注解式:

    @RequestMapping(value = "/addUser2")@RequiresRoles(value = {"admin"})public String add2() {System.out.println("新增成功");return null;}

’ 3)权限字符串形式

    @RequestMapping(value = "/addUser2")
//    @RequiresRoles(value = {"admin"})@RequiresPermissions(value = {"user:add:*"})public String add2() {System.out.println("新增成功");return null;}

十一:整合 shiro 连接数据库(16~17)

1. 数据库、表结构设计


2. 创建数据库:

-- 用户和角色的关系
CREATE TABLE `user_role` (`id` bigint(20) unsigned PRIMARY KEY AUTO_INCREMENT,`role_id` bigint(20),`user_id` bigint(20)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 角色表
CREATE TABLE `role` (`id` bigint(20) unsigned PRIMARY KEY AUTO_INCREMENT,`name` varchar(128)  default "" COMMENT '名称'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 角色与权限的关系表
CREATE TABLE `role_permission` (`id` bigint(20) unsigned PRIMARY KEY AUTO_INCREMENT,`role_id` bigint(20),`permission_id` bigint(20)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 权限表
CREATE TABLE `permission` (`id` bigint(20) unsigned PRIMARY KEY AUTO_INCREMENT,`name` varchar(128)  default "" COMMENT '名称',`url` varchar(128)  default "" COMMENT '接口路径'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3. 构建用户、角色、权限 实体类:

4. dao 层查询方法:
’ 1)根据用户名查询所有角色:

    <select id="findByUsername" resultType="com.shiro.myshirodemo02jsp.entity.RoleEntity">SELECT r.namefrom shiro_user suleft join user_role ur onsu.id = ur.user_idleft JOIN `role` r onur.role_id = r.idwhere su.username = #{username}</select>

’ 2)业务层实现:

public class MyRealm extends AuthorizingRealm {@Autowiredprivate ShiroUserService shiroUserService;@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String primaryPrincipal = (String) principals.getPrimaryPrincipal();//根据主体,获取角色信息,权限信息List<String> allRoleByUsername = shiroUserService.findAllRoleByUsername(primaryPrincipal);if (allRoleByUsername != null) {SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();simpleAuthorizationInfo.addRoles(allRoleByUsername);return simpleAuthorizationInfo;}return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {return null;}
}

6. 查询用户对应的权限字符串,并赋值:
’ 1)根据用户查询角色、根据角色查询对应的权限字符串。
’ 2)在 自定义 Realm 中赋值。

十二:SpringBoot 默认 缓存之 EhCache(21~21)

1. Cache 作用(下)
2. 引入 shiro 与 ehcache 依赖

        <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.5.3</version></dependency>

3. 在自定义 Realm中,开启缓存管理器

    // 3:创建 realm@Bean(value = "realm")public Realm realm() {CustomerRealm customerRealm = new CustomerRealm();// 修改自定义凭证匹配器HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();matcher.setHashAlgorithmName("md5");matcher.setHashIterations(1024);customerRealm.setCredentialsMatcher(matcher);// 开启缓存管理器customerRealm.setCacheManager(new EhCacheManager());customerRealm.setCachingEnabled(true);// 设置认证缓存customerRealm.setAuthenticationCachingEnabled(true);customerRealm.setAuthenticationCacheName("authenticationCacheName");// 设置授权缓存customerRealm.setAuthorizationCachingEnabled(true);customerRealm.setAuthorizationCacheName("authorizationCacheName");return customerRealm;}

十三:SpringBoot 缓存之 Redis:(22~23)

1. 使用 CacheManager;Cache 作用:

2. 引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3. yml 配置:

spring:redis:host: 114.215.173.88port: 6379

4. 配置 redis 缓存管理器:
’ 1)开启缓存:

@Configuration
public class ShiroConfig {// 3:创建 realm@Bean(value = "realm")public Realm realm(RedisCacheManager redisCacheManager) {CustomerRealm customerRealm = new CustomerRealm();// 修改自定义凭证匹配器HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();matcher.setHashAlgorithmName("md5");matcher.setHashIterations(1024);customerRealm.setCredentialsMatcher(matcher);customerRealm.setCacheManager(new RedisCacheManager());// 开启全局缓存管理器customerRealm.setCachingEnabled(true);// 设置认证缓存customerRealm.setAuthenticationCachingEnabled(true);customerRealm.setAuthenticationCacheName("authenticationCacheName");// 设置授权缓存customerRealm.setAuthorizationCachingEnabled(true);customerRealm.setAuthorizationCacheName("authorizationCacheName");return customerRealm;}}

‘ 2)自定义 shiro 缓存管理器:

@Component
public class RedisCacheManager implements CacheManager {@Autowiredprivate RedisCache redisCache;@Overridepublic <K, V> Cache<K, V> getCache(String cacheName) throws CacheException {System.out.println("cacheName ===" + cacheName);return redisCache;}}



认证数据加入缓存,user要序列化



盐不能序列化,需处理盐

补其他方法:

 2、3、4、
  1. 1

Shiro 整合 thymeleaf

1. 引入 拓展依赖:

<dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency>

2. 页面中 引入命名空间:

3. 配置文件:

4.

  1. 2
  2. 2
  3. 2
  4. 2

Shiro-编程不良人相关推荐

  1. 【编程不良人】快速入门Spring学习笔记08---事务属性、Spring整合Structs2框架(SM)、Spring整合Mybatis+Struts2(SSM)、Spring注解、SSM注解式开发

    1. 事务属性 1.1 事务传播属性 配套视频:[编程不良人]快速入门Spring,SpringBoot.SpringCloud学不好完全是因为Spring没有掌握!_哔哩哔哩_bilibili # ...

  2. 【编程不良人】快速入门SpringBoot学习笔记06---RestFul、异常处理、CORS跨域、Jasypt加密

    1. RestFul 配套视频:[编程不良人]2021年SpringBoot最新最全教程_哔哩哔哩_bilibili 1.1 引言 REST全称是(Resources) Representationa ...

  3. Hadoop 从入门到精通----leo学习编程不良人视频的笔记--part01

    编程不良人原版笔记 - https://blog.csdn.net/wei198621/article/details/111280555 part 01 hadoop 集群的搭建 – https:/ ...

  4. Springboot(编程不良人)

    Springboot(编程不良人) 文章目录 Springboot(编程不良人) 1.SpringbootApplication注解相关说明 2.配置文件拆分以及加载外部配置文件 3.管理对象的创建 ...

  5. jwt实战详解--B站编程不良人视频笔记

    文章目录 前言 一.什么是JWT 二.JWT能做什么 1.授权 2.信息交换 三.为什么使用JWT 四.JWT的结构是什么 五.使用JWT 1.引入依赖 2.生成token 3.根据令牌和签名解析数据 ...

  6. Hadoop 从入门到精通----编程不良人笔记

    编程不良人原版笔记 - https://blog.csdn.net/wei198621/article/details/111280555 part 01 hadoop 集群的搭建 – https:/ ...

  7. 【编程不良人】MongoDB最新实战教程学习笔记

    简介 视频链接:01.简介和历史_哔哩哔哩_bilibili 文档地址: https://docs.mongodb.com/manual/ MongoDB教程:MongoDB 教程 | 菜鸟教程 注意 ...

  8. 【编程不良人】SpringSecurity实战学习笔记07---授权

    配套视频:61.授权之授权核心概念_哔哩哔哩_bilibili 什么是权限管理? 权限管理核心概念 Spring Security权限管理策略 基于URL地址方式实现的权限管理 基于方法实现的权限管理 ...

  9. Docker学习视频笔记【编程不良人】

    1.Docker介绍 2.Docker与虚拟机对比 3.Docker引擎安装 4.Docker中核心概念 5.Docker核心架构图 6.配置阿里云镜像加速 Docker 配置国内镜像源_hub-mi ...

  10. B站【编程不良人】Redis教程整理学习笔记(超详细拓展)

    Redis 1. NoSQL的引言 NoSQL( Not Only SQL ),意即不仅仅是SQL, 泛指非关系型的数据库.Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨. 2. ...

最新文章

  1. spring 使用redis集群配置
  2. 设计模式复习-装饰模式
  3. 如何使用JCA (J2EE 连接器架构)实现企业应用--转载
  4. iOS系统 应用闪退或图标消失的解决办法
  5. 前端学习(2347):创建新页面和配置
  6. sqlmap源码阅读系列检查是否满足依赖
  7. 元素凸起效果_被誉为作物“生殖元素”的“硼”到底有多重要?看完你就明白了...
  8. TS Interface(接口)
  9. Jasperreports TextField自动换行
  10. 简单版本CRM 客户管理系统设计
  11. 3DMAX 切换视图+切换到摄像机视角
  12. 计算机网络的类型和特点
  13. 《C语言程序设计》江宝钏主编-习题6-1-温度转换
  14. 坑逼的PL2303与WIN11
  15. C Primer Plus (第六版) 第十四章_编程练习答案
  16. win10WLAN选项消失解决方法
  17. 关于简书签约作者饱醉豚违反简书社区原则的公示说明
  18. 关于任意群是否都是可以由其元素生成,及群中心与元素正规化子关系的分析(2009及1997群论真题)
  19. 定时清理docker image
  20. 我的2012小结:不忘初心,方得始终

热门文章

  1. 高通AudioHAL分析
  2. 高性能iOS开发--移动应用的性能
  3. Spring5中文文档【1】Spring框架概述
  4. (四)手把手带你搭建精美简洁的个人时间管理网站—相关产品调研
  5. 游戏版号恢复发放后,还有一个好消息……
  6. 【点云预处理】N种点云数据数据预处理方法 — 持续总结和更新(二)
  7. 中国六大新支柱产业十四五发展全景 附下载
  8. 医院真空管道垃圾自动收集系统
  9. 伦敦银换算就这么简单吗?
  10. Mysql表批量添加字段