参考这边文章:
https://blog.csdn.net/Katharsis_2021/article/details/133838688
数据库也是用的若依的基本数据库,ruoyi.vip
1、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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainpet</groupId>
<artifactId>spring-shiro01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-shiro02</name>
<description>spring-shiro02</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.23</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.17</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.rainpet.springshiro01.SpringShiro01Application</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2、配置文件:application.yml
server:
port: 8086
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: guest
password: 369258
type: com.alibaba.druid.pool.DruidDataSource
thymeleaf:
check-template: false
check-template-location: false
redis:
host: 127.0.0.1
port: 6379
password: myoa888
database: 0
timeout: 30000
lettuce:
pool:
max-active: 100
max-idle: 10
min-idle: 5
web:
resources:
add-mappings: false
# devtools:
# restart:
# enabled: true
# additional-paths: src/main/java
# exclude: static/**
# livereload:
# enabled: true
# port: 35729
management:
endpoints:
web:
exposure:
include: beans
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.rainpet.spring-shiro01.entity
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging:
level:
root: debug
3、ShiroConfig.java
package com.rainpet.springshiro01.config;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
@Configuration
@ComponentScan(value = "com.rainpet.springshiro01")
public class ShiroConfig {
// 1.shiroFilter:负责拦截所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 给filter设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// 默认认证界面路径---当认证不通过时跳转
shiroFilterFactoryBean.setLoginUrl("/user/login");
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<>();
filterMap.put("jwt", new JwtFilter());
shiroFilterFactoryBean.setFilters(filterMap);
// 配置系统受限资源
Map<String, String> map = new HashMap<String, String>();
map.put("/user/login","anon");
map.put("/user/register","anon");
map.put("/login","anon");
map.put("/**", "jwt");
// 所有请求通过我们自己的过滤器
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//2.创建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 给安全管理器设置realm
securityManager.setRealm(realm);
// 关闭shiro的session(无状态的方式使用shiro)
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
}
4、LoginService.java
package com.rainpet.springshiro01.service;
import com.rainpet.springshiro01.entity.SysUser;
import com.rainpet.springshiro01.utils.ResponseResult;
public interface LoginService {
ResponseResult login(SysUser user);
ResponseResult logout();
}
5、LoginServiceImpl.java
package com.rainpet.springshiro01.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rainpet.springshiro01.entity.SysUser;
import com.rainpet.springshiro01.mapper.SysUserMapper;
import com.rainpet.springshiro01.service.LoginService;
import com.rainpet.springshiro01.utils.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private RedisUtil redisCache;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private SysUserMapper sysUserMapper;
@Override
public ResponseResult login(SysUser user) {
//获取userid和password
String username = user.getUserName();
String password = user.getPassword();
QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", username);
SysUser loginUser = sysUserMapper.selectOne(queryWrapper);
if(null == loginUser){
//throw new RuntimeException("用户名或密码错误");
return ResponseResult.fail(HttpStatusEnum.BAD_REQUEST,"用户名错误!");
}
String userId = loginUser.getUserId().toString();
String pwd = loginUser.getPassword();
if(!BcryptUtil.match(password,pwd)){
//throw new RuntimeException("用户名或密码错误");
return ResponseResult.fail(HttpStatusEnum.UNAUTHORIZED,"用户名或密码错误!");
}
//使用userid生成token
String jwt = jwtUtil.createJwtToken(userId,36000L);
//authenticate存入redis
redisCache.setCacheObject("token_"+jwt,loginUser,36000, TimeUnit.SECONDS);
//把token响应给前端
HashMap<String,String> map = new HashMap<>();
map.put("token",jwt);
return ResponseResult.success(map);
}
@Override
public ResponseResult logout() {
return ResponseResult.success("退出成功");
}
}
6、LoginController.java
package com.rainpet.springshiro01.controller;
import com.rainpet.springshiro01.entity.SysUser;
import com.rainpet.springshiro01.service.impl.LoginServiceImpl;
import com.rainpet.springshiro01.utils.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class LoginController {
@Autowired
LoginServiceImpl loginServiceImpl;
@PostMapping("/user/login")
public ResponseResult login(@RequestBody SysUser user){
return loginServiceImpl.login(user);
}
@PostMapping("/hello")
public ResponseResult hello(){
return ResponseResult.success("hello");
}
}
7、SysMenuMapper.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.rainpet.springsecurity.mapper.SysMenuMapper">
<select id="selectPermsByUserId" resultType="java.lang.String">
SELECT
DISTINCT (case when m.`perms`='' then `path` else m.`perms` end)
FROM
sys_user_role ur
LEFT JOIN `sys_role` r ON ur.`role_id` = r.`role_id`
LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
LEFT JOIN `sys_menu` m ON m.`menu_id` = rm.`menu_id`
WHERE
user_id = #{userid}
</select>
</mapper>