参考笔记

1 什么是Shiro?

●Apache Shiro是一个Java 的安全(权限)框架。

●Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。

●Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等.

●下载地址: http://shiro.apache.org/

2. 有哪些功能

●Authentication: 身份认证、登录,验证用户是不是拥有相应的身份;

●Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!

●Session Manager: 会话管理,即用户登录后就是第-次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境,也可以是Web环境;

●Cryptography: 加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;

●Web Support: Web支持,可以非常容易的集成到Web环境;

●Caching: 缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率

●Concurrency: Shiro支持多线程应用的并发验证,即,如在-个线程中开启另-一个线程,能把权限自动的传

播过去

●Testing:提供测试支持;

●RunAs:允许一个用户假装为另-一个用户(如果他们允许)的身份进行访问;

●Remember Me:记住我,这个是非常常见的功能,即一-次登录后, 下次再来的话不用登录了

3. Shiro架构(外部)

从外部来看Shiro,即从应用程序角度来观察如何使用shiro完成工作:

●subject: 应用代码直接交互的对象是Subject, 也就是说Shiro的对外API核心就是Subject, Subject代表了当前的用户,这个用户不-定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager; Subject其实是一一个门面, SecurityManageer 才是实际的执行者

●SecurityManager: 安全管理器,即所有与安全有关的操作都会与SercurityManager交互, 并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色

●Realm: Shiro从Realm获取安全数据 (如用户,角色,权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是否能够进行,可以把Realm看DataSource;

4.Shiro架构(内部)

●Subject: 任何可以与应用交互的用户;

●Security Manager:相当于SpringMVC中的DispatcherSerlet; 是Shiro的心脏, 所有具体的交互都通过Security Manager进行控制,它管理者所有的Subject, 且负责进行认证,授权,会话,及缓存的管理。

●Authenticator:负责Subject认证, 是-一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了;

●Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中

的那些功能;

●Realm: 可以有-一个或者多个的realm, 可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等等,由用户提供;所以- -般在应用中都需要实现自己的realm

●SessionManager:管理Session生 命周期的组件,而Shiro并不仅仅可以用在Web环境,也可以用在普通的JavaSE环境中

●CacheManager: 缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能;

●Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于密码加密, 解密等

5.Shiro快速开始

准备工作

Github资源

  • 创建一个普通maven项目springboot-08-shiro,然后删除src目录,这样的话就可以在这个项目里新建很多model.

  • 在springboot-08-shiro里新建model hello_shiro

  • 找到文件

  • 在pom.xml中复制
    <dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId></dependency><!-- configure logging --><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><scope>runtime</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><scope>runtime</scope></dependency></dependencies>

更改细节

    <dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.1</version></dependency><!-- configure logging --><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.21</version><scope>runtime</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version><scope>runtime</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version><scope>runtime</scope></dependency></dependencies>

复制

log4j.properties

log4j.rootLogger=INFO, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n# General Apache libraries
log4j.logger.org.apache=WARN# Spring
log4j.logger.org.springframework=WARN# Default Shiro logging
log4j.logger.org.apache.shiro=INFO# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

shiro.ini

[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

然后

Quickstart.java

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;/*** Simple Quickstart application showing how to use Shiro's API.** @since 0.9 RC2*/
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 = 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()) {UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");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);}
}

注:

Quickstart报错,查了好久,发现是factory方法过时了,新版本会有异常

需要将这两行代码

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();

替换为

DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
securityManager.setRealm(iniRealm);

启动

2020-11-04 09:13:59,275 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler...
2020-11-04 09:14:00,629 INFO [Quickstart] - Retrieved the correct value! [aValue]
2020-11-04 09:14:00,630 INFO [Quickstart] - User [lonestarr] logged in successfully.
2020-11-04 09:14:00,631 INFO [Quickstart] - May the Schwartz be with you!
2020-11-04 09:14:00,631 INFO [Quickstart] - You may use a lightsaber ring.  Use it wisely.
2020-11-04 09:14:00,632 INFO [Quickstart] - You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  Here are the keys - have fun!

6.SpringBoot整合Shiro环境搭建

  • 新建SpringBoot项目,勾选web和thymeleaf

  • 保持项目清洁,删除

  • templates下新建index.html

<!DOCTYPE html>
<html lang="en"xmlns:th="https://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body><h1>首页</h1>
<p th:text="${msg}"></p></body>
</html>
  • controller包下新建MyController
package com.kwok.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class MyController {@RequestMapping({"/","/index"})public String toIndex(Model model){model.addAttribute("msg","hello,shiro");return "index";}
}
  • 测试正常

让我们继续

Subject用户

SecurityManager管理所有用户

Realm连接数据

github链接

pom.xml复制

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

发现并不好使更换为

        <!--shiro--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.8.0</version></dependency>

shiro整合mybatis

导入jar包

             <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency>

编写application.yml

spring:datasource:username: rootpassword: 123url: jdbc:mysql://localhost:3306/mybatis_05?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#Spring Boot 默认是不注入这些属性值的,需要自己绑定#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入#如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:type-aliases-package: com.kwok.pojomapper-locations: classpath:mybatis/mapper/*.xml

编写实体类

        <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version><scope>provided</scope></dependency>

User

package com.kwok.pojo;public class User {private int id;private String name;private String password;private String perms;public User() {}public User(int id, String name, String password, String perms) {this.id = id;this.name = name;this.password = password;this.perms = perms;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}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;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +", perms='" + perms + '\'' +'}';}
}

mapper包编写UserMapper

package com.kwok.mapper;import com.kwok.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Repository
@Mapper
public interface UserMapper {public User queryUserByName(String name);}

resource包下新建mybatis包下健mapper

UserMapper.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.kwok.mapper.UserMapper"><select id="queryUserByName" resultType="User" parameterType="String">select * from user where name = #{name}</select></mapper>

service层

UserService接口

package com.kwok.service;import com.kwok.pojo.User;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;@Service
@Repository
public interface UserService {public User queryUserByName(String name);}

UserServiceImpl

package com.kwok.service;import com.kwok.mapper.UserMapper;
import com.kwok.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service("UserService")
public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepublic User queryUserByName(String name) {return userMapper.queryUserByName(name);}
}

ShiroSpringbootApplicationTests中进行测试

package com.kwok;import com.kwok.service.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class ShiroSpringbootApplicationTests {@AutowiredUserServiceImpl userService;@Testvoid contextLoads() {System.out.println(userService.queryUserByName("admin"));}}
  • 测试成功

Shiro整合Thymeleaf

导入jar包

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

代码整理

结构目录

config

ShiroConfig

package com.kwok.config;//import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//ShiroFilterBean@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();//设置安全管理器bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/*anon:无需认证就能访问authc:必须认证才能访问user:必须拥有记住我功能才能访问perms:拥有某个资源的权限才能访问role:拥有某个角色权限才能访问*///拦截Map<String,String> filterMap =new LinkedHashMap<>();//授权filterMap.put("/user/add","perms[user:add]");filterMap.put("/user/update","perms[user:update]");filterMap.put("/user/*","authc");//设置登陆的请求bean.setLoginUrl("/toLogin");//设置未授权的请求bean.setUnauthorizedUrl("/noauth");bean.setFilterChainDefinitionMap(filterMap);return bean;}//DefaultWebSecurityManager@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();//关联UserRealmsecurityManager.setRealm(userRealm);return securityManager;}//创建realm对象@Beanpublic UserRealm userRealm(){return new UserRealm();}// 整合ShiroDialect:用来整合shiro thymeleaf@Beanpublic ShiroDialect getShiroDialect(){return new ShiroDialect();}}

UserRealm

package com.kwok.config;import com.kwok.pojo.User;
import com.kwok.service.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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;// 授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了授权doGetAuthorizationInfo");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//        info.addStringPermission("user:add");// 拿到当前登录的这个对象Subject subject = SecurityUtils.getSubject();User currentUser = (User) subject.getPrincipal(); // 拿到user对象info.addStringPermission(currentUser.getPerms());return info;}// 认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行了认证doGetAuthenticationInfo");// 用户名,密码~ 数据中取UsernamePasswordToken userToken = (UsernamePasswordToken) token;//连接真实数据库User user = userService.queryUserByName(userToken.getUsername());if (user==null){// 没有这个人return null;}Subject currentSubject = SecurityUtils.getSubject();Session session = currentSubject.getSession();session.setAttribute("loginUser",user);// 密码认证,shiro做,加密了return new SimpleAuthenticationInfo(user,user.getPassword(),"");}
}

controller

MyController

package com.kwok.controller;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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class MyController {@RequestMapping({"/","/index"})public String toIndex(Model model){model.addAttribute("msg","hello,shiro");return "index";}@RequestMapping("/user/add")public String add(){return "user/add";}@RequestMapping("/user/update")public String update(){return "user/update";}@RequestMapping("/toLogin")public String toLogin(){return "login";}@RequestMapping("/login")public String login(String username,String password,Model model){// 获取当前的用户Subject subject = SecurityUtils.getSubject();// 封装用户的登录数据UsernamePasswordToken token = new UsernamePasswordToken(username, password);try{subject.login(token); // 执行登录的方法,如果没有异常就说明okreturn "index";}catch (UnknownAccountException e){// 用户名不存在model.addAttribute("msg","用户名错误");return "login";}catch (IncorrectCredentialsException e){// 密码不存在model.addAttribute("msg","密码错误");return "login";}}@RequestMapping("/noauth")@ResponseBodypublic String unauthorized(){return "未授权无法访问此页面!";}
}

mapper

UserMapper

package com.kwok.mapper;import com.kwok.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Repository
@Mapper
public interface UserMapper {public User queryUserByName(String name);}

pojo

User

package com.kwok.pojo;public class User {private int id;private String name;private String password;private String perms;public User() {}public User(int id, String name, String password, String perms) {this.id = id;this.name = name;this.password = password;this.perms = perms;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}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;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +", perms='" + perms + '\'' +'}';}
}

service

UserService

package com.kwok.service;import com.kwok.pojo.User;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;@Service
@Repository
public interface UserService {public User queryUserByName(String name);}

UserServiceImpl

package com.kwok.service;import com.kwok.mapper.UserMapper;
import com.kwok.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service("UserService")
public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepublic User queryUserByName(String name) {return userMapper.queryUserByName(name);}
}

resource

UserMapper.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.kwok.mapper.UserMapper"><select id="queryUserByName" resultType="User" parameterType="String">select * from user where name = #{name}</select></mapper>

add.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>增加</title>
</head>
<body><h1>增加</h1></body>
</html>

update.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>修改</title>
</head>
<body><h1>修改</h1></body>
</html>

index.html

<!DOCTYPE html>
<html lang="en"xmlns:th="https://www.thymeleaf.org"xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body><h1>首页</h1><div th:if="${session.loginUser==null}"><a th:href="@{/toLogin}">登录</a>
</div><p th:text="${msg}"></p>
<hr><div shiro:hasPermission="user:add">
<a th:href="@{/user/add}">add</a>
</div><div shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div></body>
</html>

login.html

<!DOCTYPE html>
<html lang="en"xmlns:th="https://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录</title>
</head>
<body><h1>登录</h1>
<hr><p th:text="${msg}" style="color: red"></p><form th:action="@{/login}"><p>用户名:<input type="text" name="username"></p><p>密码:<input type="text" name="password"></p><p><input type="submit"></p>
</form></body>
</html>

application.yml

spring:datasource:username: rootpassword: 123url: jdbc:mysql://localhost:3306/mybatis_05?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#Spring Boot 默认是不注入这些属性值的,需要自己绑定#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入#如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4jfilters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:type-aliases-package: com.kwok.pojomapper-locations: classpath:mybatis/mapper/*.xml

pom.xml

<?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 https://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.6.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.kwok</groupId><artifactId>shiro-springboot</artifactId><version>0.0.1-SNAPSHOT</version><name>shiro-springboot</name><description>Demo project for Spring Boot</description><properties><java.version>11</java.version></properties><dependencies><!--shiro-thymeleaf--><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><!--shiro--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.8.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--thymeleaf--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-java8time</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

SpringBoot-集成Shiro相关推荐

  1. springboot集成shiro 前后端分离 统一处理shiro异常

    springboot集成shiro 前后端分离 统一处理shiro异常 参考文章: (1)springboot集成shiro 前后端分离 统一处理shiro异常 (2)https://www.cnbl ...

  2. SpringBoot集成Shiro安全框架

    SpringBoot集成Shiro安全框架 1.shiro的定义 2.SpringBoot集成shiro的步骤 3.完成的效果 1.shiro的定义 1.shiro的作用 认证.授权.加密.会话管理. ...

  3. springboot集成shiro实现用户登录认证

    Apache Shiro 是一个功能强大且易于使用的Java安全框架,可执行身份验证.授权.加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大 ...

  4. apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录

    小Hub领读: 导入jar包,配置yml参数,编写ShiroConfig定义DefaultWebSecurityManager,重写Realm,编写controller,编写页面,一气呵成.搞定,是个 ...

  5. Springboot集成Shiro+Redis后,@Transactional注解不起作用

    为什么80%的码农都做不了架构师?>>>    使用Springboot构建 mybatis+Shiro+Redis+Druid 的前后端分离web项目, 具体可以参考博客https ...

  6. (课堂作业)spring-boot集成shiro的步骤及代码解析

    1.创建一个简单的Springboot项目,包含shiro和mybatis-plus. 2.集成shiro 2.1引入依赖 <dependency><groupId>org.a ...

  7. 【Springboot学习】SpringBoot集成Shiro前后端分离使用redis做缓存【个人博客搭建】

    shiro-redis 目录 shiro-redis 下载 shiro-core/jedis 版本对比图 使用前 如何配置? 设置文件 Redis 独立 Redis哨兵 Redis 集群 Spring ...

  8. Springboot 集成 Shiro 入门学习

    文章目录 Shiro概述 主要特征 shiro如何工作 官方快速开始代码分析 Springboot整合Shiro 导入依赖 创建配置类ShiroConfig 创建Realm 创建控制器 创建静态页面 ...

  9. SpringBoot集成Shiro前后端分离使用redis做缓存

    文章目录 一 .shiro介绍 1.基础介绍 2.基本功能点 3.基本流程图 二. 常用的权限管理表关系 2.1. 表组成 2.2. 表结构 三.实战案例 3.1. 案例介绍 3.2. 依赖 3.3. ...

  10. SpringBoot集成shiro框架

    一 介绍: 主要用到SpringBoot.hibernate.swagger.mybatis.shiro.maven等技术. 项目使用idea.mysql数据库开发,idea要安装lombok插件否则 ...

最新文章

  1. 基于opencV的动态背景下运动目标检测及跟踪(修改版)
  2. 004_Jsp九大内置对象
  3. 对话框的MFC,一点回车就退出
  4. 英语自动提取高频词_斑马英语提分营免费体验课
  5. LeetCode: Merge k Sorted Lists
  6. Android线程机制——AsyncTask
  7. Oracle 修改字符集 为ZHS16GBK
  8. JSP内置对象实现表的增删查改
  9. nginx fastcgi python_Nginx+FastCGI+Python
  10. win7 自带计算机(for programmer)
  11. 微服务 订单交易支付系统架构演进
  12. 排队论模型(五): 有限源排队模型、服务率或到达率依赖状态的排队模型
  13. 计算机信息技术奥赛实践,高中信息技术奥赛一本全
  14. 无法打开xlsx文件_什么是XLSX文件(以及如何打开一个文件)?
  15. 5G应用加速落地,酷雷曼VR直播应时而生。
  16. YYC优雅草松鼠聚合直播系统·前端视频模块显示空白-解决办法-视频上传处理方法
  17. 一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子以及角谷定理的计算
  18. 逝随春花——OIer JCY 后续
  19. 物竞天择2 NS2 -MOD制作教程 -制作工具
  20. Epson机械手简单实例编程

热门文章

  1. Html+CSS+JS轮播图:手动轮播,自动轮播
  2. nginx 实现多端口转发
  3. DFS(深搜)算法解析
  4. 《天道》之丁元英的30句经典语录
  5. 百度又一神器发布!网友:牛逼炸了...
  6. CDC::CreateCompatibleDC 的整理(转)
  7. shardingsphere读写分离+分表【笔记】
  8. 谈谈我所了解的数据分析行业(上)
  9. 添加权限,获取到用户信息,就用户当前部门进行下拉选择
  10. Docker设置共享文件夹