SpringBoot整合Shiro、Mybatis、Thymeleaf
SpringBoot整合Shiro
-
新建一个SpringBoot项目导入Thymeleaf依赖
<dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency>
-
导入SpringBoot整合Shiro依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency>
-
创建首页以及Controller
package com.cjp.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; @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); //执行登录方法,如果没有异常就ok了 return "index"; }catch (UnknownAccountException e){ //用户名不存在 model.addAttribute("msg","用户名不存在"); return "login"; }catch (IncorrectCredentialsException e){//密码不存在 model.addAttribute("msg","用户名或密码错误"); return "login"; } } }
-
新建配置ShiroConfig
package com.cjp.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; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { //ShiroFilterFactoryBean 3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //添加内置过滤器 Map<String, String> filterMap = new LinkedHashMap<>(); //登陆拦截 filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); bean.setLoginUrl("/toLogin"); return bean; } //DefaultWebSecurityManager 2 @Bean(name = "manager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); //关联UserRealm manager.setRealm(userRealm); return manager; } //创建Realm对象, 需要自定义 1 @Bean public UserRealm userRealm(){ UserRealm userRealm = new UserRealm(); return userRealm; } }
-
自定义Realm对象:UserRealm
package com.cjp.config; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; //自定义的Realm public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = "cjp"; String password = "123"; UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; if (!usernamePasswordToken.getUsername().equals(username)){ //用户名认证 return null; //抛出错误 } return new SimpleAuthenticationInfo("",password,""); } }
项目结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRyV694o-1659748359609)(D:\Desktop\暑假学习笔记\imag\image-20220805150601569.png)]
整合Mybatis、连接数据库、整合thymeleaf
-
导入Mybatis,连接数据库的依赖
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot</artifactId> <version>2.1.1</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.1.21</version> </dependency>
-
配置数据库连接
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
-
创建实例类 User、对应的UserMapper、UserMapper.xml、UserService、UserServiceImpl
User:
package com.cjp.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; }
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.cjp.mapper.UserMapper"> <select id="queryUserByName" resultType="User" parameterType="String"> select * from user where name = #{name} </select> </mapper>
UserService:
package com.cjp.service; import com.cjp.pojo.User; public interface UserService { public User queryUserByName(String name); }
UserServiceImpl:
package com.cjp.service; import com.cjp.mapper.UserMapper; import com.cjp.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; @Override public User queryUserByName(String name) { User user = userMapper.queryUserByName(name); return user; } }
配置文件中绑定:
mybatis.type-aliases-package=com.cjp.pojo mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
-
修改UserRealm:
package com.cjp.config; import com.cjp.pojo.User; import com.cjp.service.UserServiceImpl; 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; //自定义的Realm public class UserRealm extends AuthorizingRealm { @Autowired UserServiceImpl userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("======>授权"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //拿到当前登录的用户对象 Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal();//拿到user对象 //设置当前用户权限 info.addStringPermission(currentUser.getPerms()); return info; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("=======>认证"); UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; User user = userService.queryUserByName(usernamePasswordToken.getUsername()); if (user==null){ //用户名认证 return null; //抛出错误 } Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); session.setAttribute("userSession",user); return new SimpleAuthenticationInfo(user,user.getPwd(),""); } }
-
修改ShiroConfig:
package com.cjp.config; 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 { //ShiroFilterFactoryBean 3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //添加内置过滤器 拦截 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.setFilterChainDefinitionMap(filterMap); bean.setLoginUrl("/toLogin"); //设置未授权页面 bean.setUnauthorizedUrl("/unauth"); return bean; } //DefaultWebSecurityManager 2 @Bean(name = "manager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); //关联UserRealm manager.setRealm(userRealm); return manager; } //创建Realm对象, 需要自定义 1 @Bean public UserRealm userRealm(){ UserRealm userRealm = new UserRealm(); return userRealm; } //整合ShiroDialect:用来整合Shiro thymeleaf @Bean public ShiroDialect getshiroDialect(){ return new ShiroDialect(); } }
-
页面权限展示设置 导入shiro命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
-
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> </head> <body> <h1>首页</h1> <p th:text="${msg}"></p> <hr> <div shiro:hasPermission="user:add"> <a th:href="@{/user/add}">添加</a> </div> <div shiro:hasPermission="user:update"> <a th:href="@{/user/update}">修改</a> </div> </br> <div th:if="${session.userSession}==null"> <a th:href="@{/toLogin}">登录</a> </div> </body> </html>
-
项目结构