区块链技术博客
www.b2bchain.cn

Springboot 集成 Shiro 入门学习

这篇文章主要介绍了Springboot 集成 Shiro 入门学习的讲解,通过具体代码实例进行26386 讲解,并且分析了Springboot 集成 Shiro 入门学习的详细步骤与相关技巧,需要的朋友可以参考下https://www.b2bchain.cn/?p=26386

本文实例讲述了2、树莓派设置连接WiFi,开启VNC等等的讲解。分享给大家供大家参考文章查询地址https://www.b2bchain.cn/7039.html。具体如下:

文章目录

  • Shiro概述
    • 主要特征
    • shiro如何工作
  • 官方快速开始代码分析
  • Springboot整合Shiro
    • 导入依赖
    • 创建配置类ShiroConfig
    • 创建Realm
    • 创建控制器
    • 创建静态页面
    • 配置过滤器
    • 配置Realm认证方法
  • Shiro整合Mybatis
  • 实现Realm从数据库中查找用户信息
  • Shiro授权操作
  • Shiro整合Thymeleaf
  • 退出登录操作

Shiro概述

主要特征

Springboot 集成 Shiro 入门学习

Shiro提供了如上图所示的特性,其中主要特性(其开发团队称之为应用安全的四大基石)如下:

  • Authentication – 身份认证 (与登陆相关,确定用户是谁)
  • Authorization – 确认权限 (确定用户能访问什么)
  • Session Management – 会话管理
  • Cryptography – 数据加密

shiro如何工作

Springboot 集成 Shiro 入门学习

应用代码的交互对象是 “Subject”,该对象代表了当前 “用户”,而所有用户的安全操作都会交给 SecurityManager 来管理,而管理过程中会从 Realm 中获取用户对应的角色和权限,可以把 Realm 堪称是安全数据源

使用最简单的 Shiro 应用:

  • 通过 Subject 来进行认证和授权,而 Subject 又委托给了 SecurityManager 进行管理
  • 我们需要给 SecurityManager 注入 Realm 以便其获取用户和权限进行判断
  • (也即,Shiro 不提供用户和权限的维护,需要由开发者自行通过 Realm 注入)

内部详细流程

Springboot 集成 Shiro 入门学习

三个核心组件:Subject, SecurityManager 和 Realms

  • Subject:即“当前操作用户”,它仅仅意味着“当前跟软件交互的东西”
  • SecurityManager:它是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务
  • Authenticator:负责 Subject 认证,是一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了
  • Authorizer:授权器、即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能
  • SessionManager:管理 Session 生命周期的组件;会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
  • Realm:充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个
  • CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能
  • Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密

官方快速开始代码分析

import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.ini.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.lang.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory;   public class Quickstart {      private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);      public static void main(String[] args) {          // The easiest way to create a Shiro SecurityManager with configured         // realms, users, roles and permissions is to use the simple INI config.         // We'll do that by using a factory that can ingest a .ini file and         // return a SecurityManager instance:          // Use the shiro.ini file at the root of the classpath         // (file: and url: prefixes load from files and urls respectively):         Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");         SecurityManager securityManager = factory.getInstance();          // for this simple example quickstart, make the SecurityManager         // accessible as a JVM singleton.  Most applications wouldn't do this         // and instead rely on their container configuration or web.xml for         // webapps.  That is outside the scope of this simple quickstart, so         // we'll just do the bare minimum so you can continue to get a feel         // for things.         SecurityUtils.setSecurityManager(securityManager);          // Now that a simple Shiro environment is set up, let's see what you can do:          // get the currently executing user:         // 获取当前的用户对象         Subject currentUser = SecurityUtils.getSubject();          // Do some stuff with a Session (no need for a web or EJB container!!!)         // 通过当前用户获得Session         Session session = currentUser.getSession();         session.setAttribute("someKey", "aValue");         String value = (String) session.getAttribute("someKey");         if (value.equals("aValue")) {             log.info("Retrieved the correct value! [" + value + "]");         }          // let's login the current user so we can check against roles and permissions:         // 判断当前用户是否被认证         if (!currentUser.isAuthenticated()) {                         // 通过用户名和密码生成token             UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");                          // 设置RememberMe             token.setRememberMe(true);             try {                 // 执行登录                 currentUser.login(token);             } catch (UnknownAccountException uae) {                 log.info("There is no user with username of " + token.getPrincipal());             } catch (IncorrectCredentialsException ice) {                 log.info("Password for account " + token.getPrincipal() + " was incorrect!");             } catch (LockedAccountException lae) {                 log.info("The account for username " + token.getPrincipal() + " is locked.  " +                         "Please contact your administrator to unlock it.");             }             // ... catch more exceptions here (maybe custom ones specific to your application?             catch (AuthenticationException ae) {                 //unexpected condition?  error?             }         }          //say who they are:         //print their identifying principal (in this case, a username):         log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");          //test a role:         if (currentUser.hasRole("schwartz")) {             log.info("May the Schwartz be with you!");         } else {             log.info("Hello, mere mortal.");         }          //test a typed permission (not instance-level)         if (currentUser.isPermitted("lightsaber:wield")) {             log.info("You may use a lightsaber ring.  Use it wisely.");         } else {             log.info("Sorry, lightsaber rings are for schwartz masters only.");         }          //a (very powerful) Instance Level permission:         if (currentUser.isPermitted("winnebago:drive:eagle5")) {             log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +                     "Here are the keys - have fun!");         } else {             log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");         }          //all done - log out!         currentUser.logout();          System.exit(0);     } }  

shiro.ini

# ============================================================================= # Quickstart INI Realm configuration # # For those that might not understand the references in this file, the # definitions are all based on the classic Mel Brooks' film "Spaceballs". ;) # =============================================================================  # ----------------------------------------------------------------------------- # Users and their assigned roles # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc # ----------------------------------------------------------------------------- [users] # user 'root' with password 'secret' and the 'admin' role root = secret, admin # user 'guest' with the password 'guest' and the 'guest' role guest = guest, guest # user 'presidentskroob' with password '12345' ("That's the same combination on # my luggage!!!" ;)), and role 'president' presidentskroob = 12345, president # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz' darkhelmet = ludicrousspeed, darklord, schwartz # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz' lonestarr = vespa, goodguy, schwartz  # ----------------------------------------------------------------------------- # Roles with assigned permissions #  # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc # ----------------------------------------------------------------------------- [roles] # 'admin' role has all permissions, indicated by the wildcard '*' admin = * # The 'schwartz' role can do anything (*) with any lightsaber: schwartz = lightsaber:* # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with # license plate 'eagle5' (instance specific id) goodguy = winnebago:drive:eagle5  

总结核心代码

// 获取当前的用户对象 Subject currentUser = SecurityUtils.getSubject();  // 通过当前用户获得Session Session session = currentUser.getSession();  // 判断当前用户是否被认证 currentUser.isAuthenticated      // 获取当前用户认证 currentUser.getPrincipal()  // 获取当前用户被认证的角色 currentUser.hasRole("schwartz")  // 获取用户的权限 currentUser.isPermitted("lightsaber:wield")    // 执行退出 currentUser.logout(); 

Springboot整合Shiro

导入依赖

<dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-web</artifactId>  </dependency>   <dependency>      <groupId>org.apache.shiro</groupId>      <artifactId>shiro-spring</artifactId>      <version>1.5.1</version>  </dependency>   <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-thymeleaf</artifactId>      <version>2.2.5.RELEASE</version>  </dependency> 

创建配置类ShiroConfig

package com.jason.shiro.config;  import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  /**  * @authot jason_yan  * @date 2020/6/17-11:10  */ @Configuration public class ShirConfig {      // 3、ShiroFilterFactoryBean     @Bean     public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){          ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();          // 关联 securityManager         filterFactoryBean.setSecurityManager(securityManager);          return filterFactoryBean;     }       // 2、DefaultWebSecurityManager     @Bean(name="securityManager")     public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){          DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();          // 关联UserRealm         securityManager.setRealm(userRealm);         return securityManager;     }      // 1、创建 realm 对象     @Bean     public UserRealm userRealm(){         return new UserRealm();     } }  

创建Realm

继承于 AuthorizingRealm

package com.jason.shiro.config;  import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection;  /**  * @authot jason_yan  * @date 2020/6/17-11:17  */ public class UserRealm extends AuthorizingRealm {      // 授权操作     @Override     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {         System.out.println("执行了授权AuthorizationInfo");         return null;     }      // 认证操作     @Override     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {         System.out.println("执行了认证AuthenticationInfo");         return null;     } } 

创建控制器

package com.jason.shiro.controller;  import com.sun.org.apache.xpath.internal.operations.Mod; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;  /**  * @authot jason_yan  * @date 2020/6/17-10:55  */ @Controller public class IndexController {      @GetMapping({"/index","/"})     public String toIndex(Model model){         model.addAttribute("msg","hello shiro");         return "index";     }      @GetMapping("/add")     public String toAdd(){         return "add";     }      @GetMapping("/update")     public String toUpdate(){         return "update";     } }  

创建静态页面

add和update页面 略(页面内容随便写)

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>     <h1>首页</h1>      <p th:text="${msg}"></p>      <a th:href="@{/add}">add something</a>     <a th:href="@{/update}">update something</a> </body> </html> 

配置过滤器

// 3、ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){      ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();      // 关联安全管理器     filterFactoryBean.setSecurityManager(securityManager);      // 配置过滤器     /**          * 配置哪些页面需要受保护.  以及访问这些页面需要的权限.          *  1). anon 可以被匿名访问,即不需要登录即可访问          *  2). authc 必须认证(即登录)后才可能访问的页面.          *  3). user 必须拥有 记住我 才能使用          *  4). perms 拥有对某个资源的权限才能访问          *  5). roles 拥有某个角色才能访问          *  6). logout 当前用户退出登录          */      Map<String,String> filterMap = new LinkedHashMap();     filterMap.put("/index","anon");     filterMap.put("/add","authc");     filterMap.put("/update","authc");      filterFactoryBean.setFilterChainDefinitionMap(filterMap);      // 如果没有认证(即登录)进行登录请求     filterFactoryBean.setLoginUrl("/login");     return filterFactoryBean; } 

控制器实现跳转至登录页面

@GetMapping("/login")     public String toLogin(){         return "login";     } 

配置登录页面 login.html

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>     <h1>用户登录页面</h1>     <hr>     <form th:action="@{/do/login}">         <p>username:<input type="text" name="username" placeholder="用户名"/></p>         <p>password:<input  type="password" name="password" placeholder="密码"/></p>         <p><input type="submit" value="登录"></input></p>     </form> </body> </html> 

当用户没有进行登录的时候 访问 add something update something 的 时候需要进行登录,才可以访问

配置Realm认证方法

在控制器中执行登录操作

@GetMapping("/do/login") public String login(String username, String password, Model model){      // 获取已登录的用户信息     Subject subject = SecurityUtils.getSubject();      // 封装用户的登录数据     UsernamePasswordToken token = new UsernamePasswordToken(username, password);      try {         // 执行登录         subject.login(token);         // 登陆成功返回首页          return "index";     } catch (UnknownAccountException uae) {         model.addAttribute("msg","用户名错误");	          // 同时在登录页面login.html中 获取错误信息<p th:text="${msg}" style="color: red"></p>         return "login";     } catch (IncorrectCredentialsException ice) {         model.addAttribute("msg","密码错误");         return "login";     } } 

当用户登陆信息提交后,在Realm中的doGetAuthenticationInfo()方法中对用户进行认证(查数据库匹配信息)

// 认证操作 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {     System.out.println("执行了认证AuthenticationInfo");      // token是从controller中传递过来的,在此处实现真正的登录操作      // 在数据库中获取用户名和密码     String name = "admin";     String password = "111111";      UsernamePasswordToken userToken = (UsernamePasswordToken) token;      // 判断从前端输入的用户名与数据库中用户名是否匹配     if (!userToken.getUsername().equals(name)){         return null; // 自动抛出UnknownAccountException异常     }      // 密码认证,使用shiro的SimpleAuthenticationInfo实现     SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("", password, "");      return info; } 

Shiro整合Mybatis

导入依赖

<dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId> </dependency> <dependency>     <groupId>log4j</groupId>     <artifactId>log4j</artifactId>     <version>1.2.17</version> </dependency> <dependency>     <groupId>com.alibaba</groupId>     <artifactId>druid</artifactId>     <version>1.1.20</version> </dependency>  <dependency>     <groupId>org.mybatis.spring.boot</groupId>     <artifactId>mybatis-spring-boot-starter</artifactId>     <version>2.1.3</version> </dependency>  <dependency>     <groupId>org.projectlombok</groupId>     <artifactId>lombok</artifactId>     <optional>true</optional> </dependency> 

创建数据库db_shiro并创建用户角色表

添加用户:admin,zs,ls

CREATE TABLE `tb_user` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `username` varchar(255) DEFAULT NULL,   `password` varchar(255) DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 

配置 application.yml 文件

spring:   datasource:     username: root     password: 123456     driver-class-name: com.mysql.cj.jdbc.Driver     url: jdbc:mysql://localhost:3306/db_shiro?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai     type: com.alibaba.druid.pool.DruidDataSource  mybatis:   mapper-locations: classpath:/mapper/*.xml   type-aliases-package: com.jason.shiro.entity  filters: stat,wall,log4j maxPoolPrearedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 

创建User

package com.jason.shiro.entity;  import lombok.*;  /**  * @authot jason_yan  * @date 2020/6/17-15:13  */ @Data @AllArgsConstructor @NoArgsConstructor public class User {      private int id;     private String username;     private String password; }  

在resource目录下(classpath)创建mapper文件夹 并配置UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.jason.shiro.mapper.UserMapper" >     <select id="queryUserByName" parameterType="String" resultType="User">         select * from tb_user where username = #{username}     </select> </mapper> 

创建Mapper接口

package com.jason.shiro.mapper;  import com.jason.shiro.entity.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository;  /**  * @authot jason_yan  * @date 2020/6/17-15:23  */  @Repository @Mapper public interface UserMapper {      public User queryUserByName(String username); } 

创建service

package com.jason.shiro.servce;  import com.jason.shiro.entity.User;  /**  * @authot jason_yan  * @date 2020/6/17-15:34  */ public interface UserService {      public User queryUserByName(String username); } 

创建service实现类

package com.jason.shiro.servce.impl;  import com.jason.shiro.entity.User; import com.jason.shiro.mapper.UserMapper; import com.jason.shiro.servce.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;  /**  * @authot jason_yan  * @date 2020/6/17-15:35  */ @Service public class UserServiceImpl implements UserService {      @Autowired     private UserMapper userMapper;      @Override     public User queryUserByName(String username) {         return userMapper.queryUserByName(username);     } } 

实现Realm从数据库中查找用户信息

@Autowired UserService userService;  ...      // 认证操作     @Override     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {     System.out.println("执行了认证AuthenticationInfo");      // token是从controller中传递过来的,在此处实现真正的登录操作     UsernamePasswordToken userToken = (UsernamePasswordToken) token;      // 在数据库中获取用户名和密码     User user = userService.queryUserByName(userToken.getUsername());      // 判断从前端输入的用户名与数据库中用户名是否匹配     if (user == null){         return null; // UnknownAccountException     }      // 密码认证,使用shiro的SimpleAuthenticationInfo实现     SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("", user.getPassword(), "");      return info; } 

Shiro授权操作

ShiroConfig类的getShiroFilterFactoryBean()方法中,对特定页面添加字段(权限)

针对权限匹配

@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){  	...      // 拦截部分页面     filterMap.put("/index","anon");     filterMap.put("/add","authc");     filterMap.put("/update","authc");      // 授权:指定角色的访问权限,如果没有权限的话会跳转至未授权页面     filterMap.put("/add","perms[user:add]"); // 若用户含拥有"user:add"字段,则可以访问add页面     filterMap.put("/update","perms[user:update]");// 若用户含拥有"user:update"字段,则可以访问update页面          filterFactoryBean.setFilterChainDefinitionMap(filterMap);      // 如果没有认证(即没有登录),则进行登录请求     filterFactoryBean.setLoginUrl("/login");          // 设置没有权限的用户 越权后跳转的页面     filterFactoryBean.setUnauthorizedUrl("/unauthc");      return filterFactoryBean; } 

在控制器中设置 当用户权限不足时的跳转页面

@GetMapping("/unauthc") public String unAuthc(){     return "unauthc"; } 

创建 unauthc.html 页面

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>     <h1>您当前权限不足以访问此功能</h1>     <a th:href="@{/index}">返回主页</a> </body> </html> 

Realm的doGetAuthorizationInfo()方法中对用户添加权限addStringPermission()

package com.jason.shiro.config;  import com.jason.shiro.entity.User; import com.jason.shiro.servce.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; 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.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;  /**  * @authot jason_yan  * @date 2020/6/17-11:17  */ public class UserRealm extends AuthorizingRealm {      @Autowired     UserService userService;      // 授权操作     @Override     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {                 System.out.println("执行了授权AuthorizationInfo");          SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();          // 获取当前登录对象         Subject subject = SecurityUtils.getSubject();         // 得到User对象         User currentUser = (User) subject.getPrincipal();          if (currentUser.getUsername().equals("zs")){             info.addStringPermission("user:add");             return info;         }else if (currentUser.getUsername().equals("ls")){             info.addStringPermission("user:update");             return info;         }else {             return null;         }              }      // 认证操作     @Override     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {          ...                  SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), "");          return info;     } }  

当zs登录时,赋予张三user:add字段,当ls登录时,赋予李四user:update字段,然后在过滤器中匹配相应的权限

对死代码进行改造:除了根据字段对用户进行授权操作外,和可以根据身份角色进行授权

在数据库 tb_user表中添加roles属性(也可以添加perms属性-其值为user:add/user:update):表名每个人对应的角色

其中 admin … user:admin、zs … user:add、ls … user:update

同时为entity包中 User对象添加属性

private String role; 

改造Realm中的死代码

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {         ...      // 获取当前登录对象     Subject subject = SecurityUtils.getSubject();      // 得到User对象     User currentUser = (User) subject.getPrincipal();      if (currentUser != null){         info.addRole(currentUser.getRole());         return info;     }else {         return null;     }      ... } 

在ShiroConfig中改造拦截器

@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){      ...      // 授权:指定角色的访问权限,如果没有权限的话会跳转至未授权页面     filterMap.put("/add","roles[add]"); // 用户的角色认证     filterMap.put("/update","roles[update]");      ...  } 

Shiro整合Thymeleaf

当张三登录时,只显示在自己权限范围内的功能页面,李四也是如此

Shiro整合Thymeleaf需要导入依赖

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

在ShiroConfig类中添加整合thymeleaf的Bean

// 整合ShiroDialect:用来整合shiro thymeleaf @Bean public ShiroDialect getShiroDialect(){     return new ShiroDialect(); } 

将当前用户登录的状态放入session中:如果有用户登录则加入session

在Realm认证(登录)操作中添加

// 认证操作 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {     	...             // 将当前用户信息放入session中,供前端 获取用户在线状态     Subject subject = SecurityUtils.getSubject();     Session session = subject.getSession();     session.setAttribute("loginUser",user);      // 密码认证,使用shiro的SimpleAuthenticationInfo实现     SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), "");      return info; } 

修改 index.html 主页

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"                 xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>     <h1>首页</h1>     <hr>     <p th:text="${msg}"></p>     <p th:if="${#strings.isEmpty(session.loginUser)}">         <a th:href="@{/do/login}">登录</a>     </p>      <p>         <div shiro:hasRole="add">             <a th:href="@{/add}">add something</a>         </div>          <div shiro:hasRole="update">             <a th:href="@{/update}">update something</a>         </div>     </p>  </body> </html> 

退出登录操作

在ShiroConfig 过滤器中添加

filterMap.put("/logout",“logout”);

添加退出登录的请求按钮及链接

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"                 xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>     <h1>首页</h1>     <hr>     <p th:text="${msg}"></p>     <p th:if="${#strings.isEmpty(session.loginUser)}">         <a th:href="@{/do/login}">登录</a>     </p>      <p>         <div shiro:hasRole="add">             <a th:href="@{/logout}">退出登录</a> |             <a th:href="@{/add}">add something</a>         </div>          <div shiro:hasRole="update">             <a th:href="@{/logout}">退出登录</a> |             <a th:href="@{/update}">update something</a>         </div>     </p>  </body> </html> 

本文转自互联网,侵权联系删除Springboot 集成 Shiro 入门学习

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Springboot 集成 Shiro 入门学习
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们