Springboot+Shiro+Mybatis+mysql实现权限安全认证

Shiro是Apache 的一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。Shiro 主要分为两个部分就是认证和授权两部分

一、介绍

  1. Subject代表了当前用户的安全操作

  2. SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

  3. Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。

  4. Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。

  5. Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

  6. sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上。

Shiro相关类介绍

  • (1)Authentication 认证 —— 用户登录

  • (2)Authorization 授权 —- 用户具有哪些权限

  • (3)Cryptography 安全数据加密

  • (4)Session Management 会话管理

  • (5)Web Integration web系统集成

  • (6)Interations 集成其它应用,spring、缓存框架

二、依赖引入

完整的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" 		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 	<modelVersion>4.0.0</modelVersion> 	<parent> 		<groupId>org.springframework.boot</groupId> 		<artifactId>spring-boot-starter-parent</artifactId> 		<version>2.4.1</version> 		<relativePath></relativePath> <!-- lookup parent from repository --> 	</parent> 	<groupId>com.gt.shiro</groupId> 	<artifactId>com.sunyue.shiro</artifactId> 	<version>1.0-SNAPSHOT</version> 	<packaging>jar</packaging> 	<properties> 		<java.version>1.8</java.version> 		<druid.verzion>1.1.10</druid.verzion> 		<pagehelper.version>1.2.10</pagehelper.version> 		<mybatis.version>2.1.4</mybatis.version> 		<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version> 	</properties> 	<dependencies> 		<dependency> 			<groupId>org.springframework.boot</groupId> 			<artifactId>spring-boot-starter-web</artifactId> 			<!-- 排除默认的tomcat --> 			<exclusions> 				<exclusion> 					<groupId>org.springframework.boot</groupId> 					<artifactId>spring-boot-starter-tomcat</artifactId> 				</exclusion> 			</exclusions> 		</dependency> 		<!-- 重新依赖Jetty的starter --> 		<dependency> 			<groupId>org.springframework.boot</groupId> 			<artifactId>spring-boot-starter-jetty</artifactId> 		</dependency> 		<dependency> 			<groupId>org.mybatis.spring.boot</groupId> 			<artifactId>mybatis-spring-boot-starter</artifactId> 			<version>${mybatis.version}</version> 		</dependency> 		<dependency> 			<groupId>org.springframework.boot</groupId> 			<artifactId>spring-boot-starter-thymeleaf</artifactId> 		</dependency> 		<dependency> 			<groupId>com.github.theborakompanioni</groupId> 			<artifactId>thymeleaf-extras-shiro</artifactId> 			<version>2.0.0</version> 		</dependency> 		<!--shiro整合spring--> 		<dependency> 			<groupId>org.apache.shiro</groupId> 			<artifactId>shiro-spring</artifactId> 			<version>1.4.0</version> 		</dependency> 		<dependency> 			<groupId>com.alibaba</groupId> 			<artifactId>druid-spring-boot-starter</artifactId> 			<version>${druid.verzion}</version> 		</dependency> 		<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter --> 		<dependency> 			<groupId>com.github.pagehelper</groupId> 			<artifactId>pagehelper-spring-boot-starter</artifactId> 			<version>${pagehelper.version}</version> 		</dependency> 		<dependency> 			<groupId>mysql</groupId> 			<artifactId>mysql-connector-java</artifactId> 			<scope>runtime</scope> 		</dependency> 		<dependency> 			<groupId>org.projectlombok</groupId> 			<artifactId>lombok</artifactId> 			<optional>true</optional> 		</dependency> 		<dependency> 			<groupId>org.springframework.boot</groupId> 			<artifactId>spring-boot-starter-test</artifactId> 			<scope>test</scope> 		</dependency> 	</dependencies> 	<build> 		<plugins> 			<!-- spring boot maven插件 --> 			<plugin> 				<groupId>org.springframework.boot</groupId> 				<artifactId>spring-boot-maven-plugin</artifactId> 				<configuration> 					<mainClass>com.gt.shiro.SpringShiroApplication</mainClass> 				</configuration> 			</plugin> 		</plugins> 	</build> </project> 

三、配置文件

application.yml配置文件: # 开发时关闭缓存,不然没法看到实时页面 spring.thymeleaf.cache=false # 用非严格的 HTML spring.thymeleaf.mode=HTML spring.thymeleaf.encoding=utf-8 spring.thymeleaf.servlet.content-type=text/html spring.datasource.druid.url=jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.druid.username=root spring.datasource.druid.password=admin spring.datasource.druid.initial-size=1 spring.datasource.druid.min-idle=1 spring.datasource.druid.max-active=20 spring.datasource.druid.test-on-borrow=true #springbootjdbc导入包不和以前一样 spring.datasource.druid.driver-class-name= com.mysql.cj.jdbc.Driver mybatis.type-aliases-package=com.gt.shiro.entity mybatis.mapper-locations=classpath:mapper/*.xml #打印数据库的操作 logging.level.com.example.springsecurity.dao=debug #redis缓存 ### 配置Redis mybatis.configuration.cache-enabled=true # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=... # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password=sunyue # 连接池最大连接数(使用负值表示没有限制) spring.redis.jedis.pool.max-idle=200 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.jedis.pool.max-wait=-1 # 连接池中的最小空闲连接 spring.redis.jedis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=1000 

Shiro两个重要的配置类:

  • 1.UserRealm

      package com.gt.shiro.config;   import com.gt.shiro.entity.TestUser;   import com.gt.shiro.server.TestUserServer;   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.ArrayList;   import java.util.HashSet;   import java.util.List;   import java.util.Set;   public class UserRealm extends AuthorizingRealm {   	@Autowired   	private TestUserServer testUserServer;   	/**   	 * 执行授权逻辑   	 *   	 * @param principalCollection   	 * @return   	 */   	@Override   	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {   		System.out.println("执行授权逻辑");   		/*获取当前登录的用户信息*/   		Subject subject = SecurityUtils.getSubject();   		TestUser testUser = (TestUser) subject.getPrincipal();   		//设置角色,多个角色   		/*Set<String> rolesSet = new HashSet<>();   		rolesSet.add(testUser.getRole());*/   		//SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(rolesSet);   		//给资源进行授权   		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();   		/*可以在以下list加入多个权限*/   		/*List<String> roles = new ArrayList<>();   		roles.add(testUser.getPerms());   		info.addRoles(roles);*/   		//设置权限   		info.addRole(testUser.getRole());   		//需要判断权限是否为空值(null是没有地址,""是有地址但是里面的内容是空的)   		if (testUser.getPerms() != null && !testUser.getPerms().equals("")) {   			info.addStringPermission(testUser.getPerms());   		}   		return info;   	}   	/**   	 * 执行认证逻辑   	 *   	 * @param authenticationToken   	 * @return   	 * @throws AuthenticationException   	 */   	@Override   	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {   		System.out.println("执行认证逻辑");   		/*获取令牌*/   		UsernamePasswordToken passwordToken = (UsernamePasswordToken) authenticationToken;   		//取出用户名并且判断用户名是否和数据库一致   		TestUser testUser = testUserServer.selectOneByName(passwordToken.getUsername());   		if (testUser != null) {   			//进行认证,将正确数据给shiro处理   			//密码不用自己比对,AuthenticationInfo认证信息对象,一个接口,new他的实现类对象SimpleAuthenticationInfo   			/*    第一个参数随便放,可以放user对象,程序可在任意位置获取 放入的对象   			 * 第二个参数必须放密码,   			 * 第三个参数放 当前realm的名字,因为可能有多个realm*/   			//若密码不正确则返回IncorrectCredentialsException异常   			return new SimpleAuthenticationInfo(testUser, testUser.getPassword(), this.getName());   		}   		//若用户名不存在则返回UnknownAccountException异常   		return null;   	}   } 
  • 2.ShiroConfig

      package com.gt.shiro.config;   import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;   import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;   import org.apache.shiro.spring.web.ShiroFilterFactoryBean;   import org.apache.shiro.mgt.SecurityManager;   import org.apache.shiro.web.mgt.DefaultWebSecurityManager;   import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;   import org.springframework.beans.factory.annotation.Qualifier;   import org.springframework.context.annotation.Bean;   import org.springframework.context.annotation.Configuration;   import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;   import java.util.LinkedHashMap;   import java.util.Map;   import java.util.Properties;   @Configuration   public class ShiroConfig {   	@Bean   	public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {   		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();   		//设置安全管理器   		shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);   		//添加一些Shiro的内置过滤器   		/**   		 * Shiro 的内置过滤器可以实现权限的相关拦截   		 * 常用过滤器   		 * 1.anon:无需认证   		 * 2.authc:必须认证才能访问   		 * 3.user:如果使用rememberme功能可以访问   		 * 4.perms:对应权限才能访问   		 * 5.role:对应角色才能访问   		 */   		//登录状态下才可以访问main页面,manage权限可访问manage页面,admin角色可访问admin页面   		Map<String, String> filterMap = new LinkedHashMap<String, String>();   		filterMap.put("/main", "authc");   		filterMap.put("/manage", "perms[manage]");   		filterMap.put("/admin", "roles[admin]");   		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);   		//未登录状态下访问将跳转至login页面   		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面   		shiroFilterFactoryBean.setLoginUrl("/login");   		// 登录成功后要跳转的链接   		shiroFilterFactoryBean.setSuccessUrl("/");   		//无授限状态下访问将请求unauthor   		shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");   		return shiroFilterFactoryBean;   	}   	@Bean(name = "securityManager")   	public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {   		DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();   		//DefaultWebSecurityManager需要关联一个Realm   		defaultWebSecurityManager.setRealm(userRealm);   		return defaultWebSecurityManager;   	}   	/**   	 * 创建realm   	 */   	@Bean(name = "userRealm")   	public UserRealm getRealm() {   		return new UserRealm();   	}   	@Bean   	public ShiroDialect shiroDialect() {   		return new ShiroDialect();   	}   	/**   	 * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)   	 * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能   	 *   	 * @return   	 */   	@Bean   	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {   		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();   		advisorAutoProxyCreator.setProxyTargetClass(true);   		return advisorAutoProxyCreator;   	}   	/**   	 * 开启 shiro 的@RequiresPermissions注解   	 *   	 * @param securityManager   	 * @return   	 */   	@Bean   	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {   		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();   		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);   		return authorizationAttributeSourceAdvisor;   	}   	/**   	 * shiro出现权限异常可通过此异常实现制定页面的跳转(或接口跳转)   	 *   	 * @return   	 */   	@Bean   	public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {   		SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();   		Properties properties = new Properties();   		/*未授权处理页*/   		properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/error.html");   		/*身份没有验证*/   		properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/error.html");   		resolver.setExceptionMappings(properties);   		return resolver;   	}   } 

四、数据连接和业务逻辑

  • 1.实体类

      package com.gt.shiro.entity;   import lombok.Data;   import lombok.experimental.Accessors;   import java.io.Serializable;   import java.util.Date;   @Data   @Accessors(chain = true)   public class TestUser implements Serializable {   	private Integer id;   	private String username;   	private String password;   	/*权限*/   	private String perms;   	/*角色*/   	private String role;   	/*加盐密码*/   	private String salt;   } 
  • 2.Dao和Mapper

      package com.gt.shiro.dao;   import com.gt.shiro.entity.TestUser;   import org.apache.ibatis.annotations.Mapper;   import java.util.List;   @Mapper   public interface TestUserMapper {   	List<TestUser> findAll();   	TestUser selectOne(Integer id);   	TestUser selectOneByName(String username);   	void insert(TestUser testUser);   	void update(TestUser testUser);   	void delete(Integer id);   } 

<?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.gt.shiro.dao.TestUserMapper"> 	<select id="findAll"  resultType="TestUser"> 	   select * from test_user 	</select> 	<select id="selectOne" resultType="TestUser"> 	   select * from test_user where id=#{id} 	</select> 	<select id="selectOneByName" resultType="TestUser"> 	   select * from test_user where username=#{username} 	</select> 	<insert id="insert"> 		insert into test_user (id,username,password,perms,role,salt) value (#{id},#{username},#{password},#{perms},#{role},#{salt}) 	</insert> 	<update id="update"> 		update test_user set username = #{username},password=#{password},perms=#{perms},role=#{role},salt=#{salt} where id = #{id} 	</update> 	<delete id="delete"> 		delete from test_user where id = #{id} 	</delete> </mapper> 
  • 3.业务层及其实现

      package com.gt.shiro.server;   import com.gt.shiro.entity.TestUser;   import org.springframework.stereotype.Service;   import java.util.List;   @Service   public interface TestUserServer {   	/*查询所有*/   	List<TestUser> selectAll();   	/*查询一个用户*/   	TestUser selectByOne(Integer id);   	/*通过名字查询一个用户*/   	TestUser selectOneByName(String name);   	/*增加一个用户*/   	void insert(TestUser testUser);   	/*删除一个用户*/   	void delete(Integer id);   	/*更新一个用户*/   	void update(TestUser testUser);   } 

package com.gt.shiro.server.serverImpl; import com.gt.shiro.dao.TestUserMapper; import com.gt.shiro.entity.TestUser; import org.apache.shiro.crypto.SecureRandomNumberGenerator; import org.apache.shiro.crypto.hash.SimpleHash; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.sunyue.shiro.server.TestUserServer; import java.util.List; @Service public class TestUserServerImpl implements TestUserServer { 	@Autowired 	private TestUserMapper testUserMapper; 	@Override 	public List<TestUser> selectAll() { 		return testUserMapper.findAll(); 	} 	@Override 	public TestUser selectByOne(Integer id) { 		return testUserMapper.selectOne(id); 	} 	@Override 	public TestUser selectOneByName(String name) { 		return testUserMapper.selectOneByName(name); 	} 	@Override 	public void insert(TestUser testUser) { 		//加密写法 		String salt = new SecureRandomNumberGenerator().nextBytes().toString(); 		String password= new SimpleHash("md5",testUser.getPassword(),salt,2).toString(); 		testUser.setPassword(password); 		testUser.setSalt(salt); 		testUserMapper.insert(testUser); 	} 	@Override 	public void delete(Integer id) { 		testUserMapper.delete(id); 	} 	@Override 	public void update(TestUser testUser) { 		testUserMapper.update(testUser); 	} } 
  • 4.控制层

      package com.gt.shiro.controller;   import com.gt.shiro.entity.TestUser;   import com.gt.shiro.server.TestUserServer;   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.crypto.hash.SimpleHash;   import org.apache.shiro.subject.Subject;   import org.springframework.beans.factory.annotation.Autowired;   import org.springframework.stereotype.Controller;   import org.springframework.ui.Model;   import org.springframework.web.bind.annotation.*;   @Controller   public class indexController {   	@Autowired   	private TestUserServer testUserServer;   	@GetMapping("/{url}")   	public String redirect(@PathVariable("url") String url) {   		return url;   	}   	@RequestMapping(value = {"/", "/index"}, method = RequestMethod.GET)   	private String index() {   		return "index";   	}   	@PostMapping("/login")   	public String login(String username, String password, Model model) {   		Subject subject = SecurityUtils.getSubject();   		TestUser testUser = testUserServer.selectOneByName(username);   		if (testUser != null) {   			//根据salt值和用户输入的密码计算加密后的密码   			String salt = testUser.getSalt();   			password = new SimpleHash("md5", password, salt, 2).toString();   			System.out.println(password);   		}   		UsernamePasswordToken token = new UsernamePasswordToken(username, password);   		//UsernamePasswordToken token = new UsernamePasswordToken(username, testUser.getPassword());(不加密写法)   		try {   			//将用户名和密码通过token传给shiro进行认证   			subject.login(token);   			TestUser user = (TestUser) subject.getPrincipal();   			subject.getSession().setAttribute("testUser", user);   			return "index";   		} catch (UnknownAccountException e) {   			e.printStackTrace();   			model.addAttribute("msg", "用户名不存在");   			return "login";   		} catch (IncorrectCredentialsException e) {   			e.printStackTrace();   			model.addAttribute("msg", "密码有误");   			return "login";   		}   	}   	@ResponseBody   	@GetMapping("/unauthor")   	public String unauthor() {   		return "权限不足,无法访问";   	}   	@GetMapping("/logout")   	public String logout() {   		Subject subject = SecurityUtils.getSubject();   		subject.logout();   		return "login";   	}   	@PostMapping("/register")   	public String register(TestUser testUser, Model model) {   		String username = testUser.getUsername();   		String password = testUser.getPassword();   		if (username ** null || username.equals("")) {   			model.addAttribute("msg", "用户名不能为空");   			return "register";   		} else if (password ** null || password.equals("")) {   			model.addAttribute("msg", "密码不能为空");   			return "register";   		} else if (testUserServer.selectOneByName(username) != null) {   			model.addAttribute("msg", "用户名已被占用");   			return "register";   		} else {   			testUserServer.insert(testUser);   			return "login";   		}   	}   } 
  • 5.前端页面

    • (1)index.html

        <!DOCTYPE html>   <html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymrleaf.org/thymeleaf-extras-shiro">   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <div th:if="${session.testUser != null}">   		<span th:text="'欢迎回来 '+${session.testUser.username}+'!  '">   		</span><a href="/logout">退出</a>   </div>   <a href="/main">main</a>   <span shiro:hasPermission="manage"> | <a href="/manage">manage</a></span>   <span shiro:hasRole="admin"> | <a href="/admin">admin</a></span>   <br>   </body>   </html> 
    • (2)login.html

        <!DOCTYPE html>   <html xmlns:th="http://www.thymeleaf.org">   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <form action="/login" method="post">   	<span th:text="${msg}" style="color: red"></span>   	<table>   		<tr>   			<td>用户名:</td>   			<td><input type="text" name="username"/></td>   		</tr>   		<tr>   			<td>密码:</td>   			<td><input type="password" name="password"/></td>   		</tr>   		<tr>   			<td><input type="submit" value="登录"/></td>   			<td><a href="/register">   				<button type="button" value="注册">注册</button>   			</a>   			</td>   		</tr>   	</table>   </form>   </body>   </html> 
    • (3)register.html

        <!DOCTYPE html>   <html xmlns:th="http://www.thymeleaf.org">   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <form action="/register" method="post">   	<span th:text="${msg}" style="color: red"></span>   	<table>   		<tr>   			<td>用户名:</td>   			<td><input type="text" name="username"/></td>   		</tr>   		<tr>   			<td>密码:</td>   			<td><input type="password" name="password"/></td>   		</tr>   		<tr>   			<td><input type="submit" value="注册"/></td>   		</tr>   	</table>   </form>   </body>   </html> 
    • (4)main.html

        <!DOCTYPE html>   <html>   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <h1>main</h1>   </body>   </html> 
    • (5)manage.html

        <!DOCTYPE html>   <html>   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <h1>manage</h1>   </body>   </html> 
    • (6)admin.html

        <!DOCTYPE html>   <html>   <head>   	<meta charset="UTF-8">   	<title>Insert title here</title>   	<link rel="shortcut icon" href="#"/>   </head>   <body>   <h1>admin</h1>   </body>   </html> 
  • 6.数据库文件

      /*   Navicat MySQL Data Transfer   Source Server         : sunyue   Source Server Version : 50724   Source Host           : localhost:3306   Source Database       : shiro   Target Server Type    : MYSQL   Target Server Version : 50724   File Encoding         : 65001   Date: 2021-01-11 22:00:47   */   SET FOREIGN_KEY_CHECKS=0;   -- ----------------------------   -- Table structure for test_user   -- ----------------------------   DROP TABLE IF EXISTS `test_user`;   CREATE TABLE `test_user` (     `id` int(11) NOT NULL AUTO_INCREMENT,     `username` varchar(120) DEFAULT NULL,     `password` varchar(120) DEFAULT NULL,     `perms` varchar(120) DEFAULT NULL,     `role` varchar(120) DEFAULT NULL,     `salt` varchar(100) DEFAULT NULL,     PRIMARY KEY (`id`)   ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4;   -- ----------------------------   -- Records of test_user   -- ----------------------------   INSERT INTO `test_user` VALUES ('4', 'admin', '4867df2e009d0096c4cd8d9be8cc104c', 'manage', 'admin', 'GQR2m1N1o3nSLjtOzMITRQ**');   INSERT INTO `test_user` VALUES ('5', 'user', '636502f40cf197dd2f4b19f56f475b24', '', '', 'Kxw3HZiFmgnlUu8fmjMY7Q**');   INSERT INTO `test_user` VALUES ('6', 'user1', '43f3133aa7e0ef9cf8373521dff8d8e8', 'manage', null, 'J8fn4HpauvNOrlUaRl/Spg**');   INSERT INTO `test_user` VALUES ('7', '1', '1', 'manage', null, null); 
发表评论

评论已关闭。

相关文章