浅谈Shiro安全框架


Shiro

    • 一,什么是Shiro
    • 二,Shiro核心组件
    • 三,Shiro的运行机制图
    • 四,Shiro的认证和授权规则
    • 五,SpringBoot整合Shiro
      • 使用Shiro做权限管理
          • 1,数据库
          • 2,创建springboot项目,导入依赖
          • 3,编写yml文件
          • 4,编写实体类
          • 5,编写dao
          • 6,编写service及实现类
          • 7,编写realm类
          • 8,编写config类
          • 9,编写controller类
          • 10,页面
          • 测试结果
          • 代码下载地址

一,什么是Shiro 官网
Shiro是一款主流的java安全框架,不依赖任何容器可以运行在javase和javaee项目中,它的主要作用
是访问系统的用户进行身份认证,授权,会话管理,加密等操作
Shiro就是用来解决安全管理的系统化框架
二,Shiro核心组件
  • UsernamePasswordToken:Shiro用来封装用户登录信息,使用用户的登录信息来创建令牌Token
  • SecurityManager:Shiro的核心部分,负责安全认证和授权
  • Suject:Shiro的一个抽象概念,包含了用户信息
  • Realm:开发者自定义的模板,根据项目的需求验证和授权的逻辑全部写在Realm中
  • AuthenticationInfo:用户的角色信息集合,认证时使用
  • AuthorzationInfo:角色的权限信息集合,授权时使用
  • DefaultWebSecurityManager:安全管理器,开发者自定义的Realm需要注入到DefaultWebSecurityManager进行管理才能生效
  • ShiroFIlterFactoryBean:过滤器工作,Shiro的基本运行机制是开发者定制规则,Shiro去执行,具体的执行操作就是由ShiroFIlterFactoryBean窗机 的一个个Filter对象来完成的
三,Shiro的运行机制图 浅谈Shiro安全框架
文章图片

四,Shiro的认证和授权规则
  • 认证过滤器
    • anon:无需认证
    • authc:必须认证
    • authcBasic:需要通过HttpBasic认证
    • user:不一定通过认证,只需要曾经被Shiro记录即可
  • 授权过滤器
    • Perms:必须拥有某个权限才能访问
    • role:必须拥有某个角色才能访问
    • port:请求的端口必须是指定值才可以
    • rest:请求必须基于RestFul风格
    • ssl:必须是安全的url请求,协议HTTPS
五,SpringBoot整合Shiro 使用Shiro做权限管理
1,数据库
-- MySQL dump 10.13Distrib 8.0.19, for Win64 (x86_64) -- -- Host: 127.0.0.1Database: test -- ------------------------------------------------------ -- Server version 8.0.19/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!50503 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Table structure for table `account` --DROP TABLE IF EXISTS `account`; /*!40101 SET @saved_cs_client= @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `account` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL, `password` varchar(20) DEFAULT NULL, `perms` varchar(20) DEFAULT NULL, `role` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `account` --LOCK TABLES `account` WRITE; /*!40000 ALTER TABLE `account` DISABLE KEYS */; INSERT INTO `account` VALUES (1,'zs','123123','',''),(2,'ls','123123','manage','administrator'),(3,'ww','123123','',''); /*!40000 ALTER TABLE `account` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2020-06-04 14:10:15

2,创建springboot项目,导入依赖
4.0.0org.springframework.boot spring-boot-starter-parent 2.1.11.RELEASE com.bd13 springboot-shiro 0.0.1-SNAPSHOT springboot-shiro Demo project for Spring Boot1.8 org.apache.shiro shiro-spring 1.5.3 mysql mysql-connector-java com.baomidou mybatis-plus-boot-starter 3.3.1.tmp com.github.theborakompanioni thymeleaf-extras-shiro 2.0.0 org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test >test org.springframework.boot spring-boot-maven-plugin

3,编写yml文件
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 09301225 url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8 thymeleaf: prefix: classpath:/templates/ suffix: .html mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4,编写实体类
package com.bd13.springbootshiro.entity; public class Account {private Integer id; private String username; private String password; private String perms; private String role; public Integer getId() {return id; }public void setId(Integer id) {this.id = id; }public String getUsername() {return username; }public void setUsername(String username) {this.username = username; }public String getPassword() {return password; }public void setPassword(String password) {this.password = password; }public String getPerms() {return perms; }public void setPerms(String perms) {this.perms = perms; }public String getRole() {return role; }public void setRole(String role) {this.role = role; } }

5,编写dao
package com.bd13.springbootshiro.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.bd13.springbootshiro.entity.Account; public interface AccountMapper extends BaseMapper {}

6,编写service及实现类
package com.bd13.springbootshiro.service; import com.bd13.springbootshiro.entity.Account; public interface AccountService {public Account findByUsername(String username); }

package com.bd13.springbootshiro.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.bd13.springbootshiro.entity.Account; import com.bd13.springbootshiro.mapper.AccountMapper; import com.bd13.springbootshiro.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class AccountServiceImpl implements AccountService {@Autowired private AccountMapper accountMapper; @Override public Account findByUsername(String username) {QueryWrapper wrapper = new QueryWrapper(); wrapper.eq("username",username); return accountMapper.selectOne(wrapper); } }

7,编写realm类
package com.bd13.springbootshiro.realm; import com.bd13.springbootshiro.entity.Account; import com.bd13.springbootshiro.service.AccountService; 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; import java.util.HashSet; import java.util.Set; public class AccountRealm extends AuthorizingRealm {@Autowired private AccountService accountService; /** * 授权 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {//获取当前登录的用户信息 Subject subject= SecurityUtils.getSubject(); Account account = (Account) subject.getPrincipal(); //设置角色 Set> roles=new HashSet<>(); roles.add(account.getRole()); SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(roles); //设置权限 info.addStringPermission(account.getPerms()); return info; }@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken; Account account = accountService.findByUsername(token.getUsername()); if (account != null){return new SimpleAuthenticationInfo(account,account.getPassword(),getName()); } return null; } }

8,编写config类
package com.bd13.springbootshiro.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.bd13.springbootshiro.realm.AccountRealm; 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; import java.util.Hashtable; import java.util.Map; @Configuration public class ShiroConfig {@Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); //权限设置 Map,String> map=new Hashtable<>(); map.put("/main","authc"); //map.put("/manage","perms[manage]"); //map.put("/administrator","roles[administrator]"); factoryBean.setFilterChainDefinitionMap(map); //设置登录页面 factoryBean.setLoginUrl("/login"); //设置未授权页面 factoryBean.setUnauthorizedUrl("/unaurh"); return factoryBean; }@Bean public DefaultWebSecurityManager securityManager(@Qualifier("accountRealm") AccountRealm accountRealm){DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(accountRealm); return manager; }@Bean public AccountRealm accountRealm(){return new AccountRealm(); }@Bean public ShiroDialect shiroDialect(){return new ShiroDialect(); } }

9,编写controller类
package com.bd13.springbootshiro.controller; import com.bd13.springbootshiro.entity.Account; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class AccountController {@GetMapping("/{url}") public String redirect(@PathVariable("url")String url){return url; } @PostMapping("/login") public String login(String username, String password, Model model){Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try{subject.login(token); Account account= (Account) subject.getPrincipal(); subject.getSession().setAttribute("account",account); return "index"; }catch (UnknownAccountException e){model.addAttribute("msg","用户名错误!"); return "login"; }catch (IncorrectCredentialsException e){model.addAttribute("msg","密码错误!"); return "login"; } }@GetMapping("/unauth") @ResponseBody public String unauth(){return "未授权,无法访问!"; }@GetMapping("/logout") public String logout(){Subject subject = SecurityUtils.getSubject(); subject.logout(); return "login"; } }

10,页面 login.html
Title - 锐客网
th:text="${msg}" style="color: red">
用户名:
密码:

index.html
Title - 锐客网 index
th:text="${session.account.username}+'欢迎回来!'">退出
main

main.html
Title - 锐客网 main

manage.html
Title - 锐客网 manage

administrator.html
Title - 锐客网 administator

测试结果 普通用户登录
浅谈Shiro安全框架
文章图片

管理员
浅谈Shiro安全框架
文章图片

超级管理员
浅谈Shiro安全框架
文章图片

代码下载地址 【浅谈Shiro安全框架】代码下载地址

    推荐阅读