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

cnblogs 2024-07-06 08:09:00 阅读 70

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文件如下:

<code><?xml version="1.0" encoding="UTF-8"?>code>

<project xmlns="http://maven.apache.org/POM/4.0.0"code>

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"code>

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">code>

<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"?>code>

<!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">code>

<select resultType="TestUser">code>

select * from test_user

</select>

<select resultType="TestUser">code>

select * from test_user where id=#{id}

</select>

<select resultType="TestUser">code>

select * from test_user where username=#{username}

</select>

<insert >

insert into test_user (id,username,password,perms,role,salt) value (#{id},#{username},#{password},#{perms},#{role},#{salt})

</insert>

<update >

update test_user set username = #{username},password=#{password},perms=#{perms},role=#{role},salt=#{salt} where id = #{id}

</update>

<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">code>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </head>

      <body>

      <div th:if="${session.testUser != null}">code>

      <span th:text="'欢迎回来 '+${session.testUser.username}+'! '">code>

      </span><a href="/logout">退出</a>code>

      </div>

      <a href="/main">main</a>code>

      <span shiro:hasPermission="manage"> | <a href="/manage">manage</a></span>code>

      <span shiro:hasRole="admin"> | <a href="/admin">admin</a></span>code>

      <br>

      </body>

      </html>

    • (2)login.html

      <!DOCTYPE html>

      <html xmlns:th="http://www.thymeleaf.org">code>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </head>

      <body>

      <form action="/login" method="post">code>

      <span th:text="${msg}" ></span>code>

      <table>

      <tr>

      <td>用户名:</td>

      <td><input type="text" name="username"/></td>code>

      </tr>

      <tr>

      <td>密码:</td>

      <td><input type="password" name="password"/></td>code>

      </tr>

      <tr>

      <td><input type="submit" value="登录"/></td>code>

      <td><a href="/register">code>

      <button type="button" value="注册">注册</button>code>

      </a>

      </td>

      </tr>

      </table>

      </form>

      </body>

      </html>

    • (3)register.html

      <!DOCTYPE html>

      <html xmlns:th="http://www.thymeleaf.org">code>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </head>

      <body>

      <form action="/register" method="post">code>

      <span th:text="${msg}" ></span>code>

      <table>

      <tr>

      <td>用户名:</td>

      <td><input type="text" name="username"/></td>code>

      </tr>

      <tr>

      <td>密码:</td>

      <td><input type="password" name="password"/></td>code>

      </tr>

      <tr>

      <td><input type="submit" value="注册"/></td>code>

      </tr>

      </table>

      </form>

      </body>

      </html>

    • (4)main.html

      <!DOCTYPE html>

      <html>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </head>

      <body>

      <h1>main</h1>

      </body>

      </html>

    • (5)manage.html

      <!DOCTYPE html>

      <html>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </head>

      <body>

      <h1>manage</h1>

      </body>

      </html>

    • (6)admin.html

      <!DOCTYPE html>

      <html>

      <head>

      <meta charset="UTF-8">code>

      <title>Insert title here</title>

      <link rel="shortcut icon" href="#"/>code>

      </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);



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。