Spring Boot+Security+Mybatis小实例
-->数据库表
CREATE TABLE `auth` (
`ids` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`aut` varchar(20) DEFAULT NULL,
PRIMARY KEY (`ids`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci KEY_BLOCK_SIZE=1
-->这是准备的角色信息数据
--->aut表示所对应的角色
-->新建一个SpringBoot项目
-->我是用idea,jdk选择1.8以上
-->各个名字自行命名
-->添加部分依赖,后面再往pom.xml加入
-->加入Security依赖
-->加入SQL依赖
-->点击下一步完成构建项目
-->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 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.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.security</groupId>
<artifactId>security-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>security-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-->application.yml配置文件
spring:
datasource:
# 数据源基本配置
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/user?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
# 数据源其他配置
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,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
# 指定全局配置文件位置
config-location: classpath:mybatis/mybatis-config.xml
# 指定sql映射文件位置
mapper-locations: classpath:mybatis/mapper/*.xml
总体结构
-->mybatis-config.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
-->EmployeeMapper.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.security.securitydemo.mapper.AutMapper">
<!-- public Employee getEmpById(Integer id);
public void insertEmp(Employee employee);-->
<select id="finall" resultType="com.security.securitydemo.pojo.Auth">
SELECT * FROM auth
</select>
<select id="getuser" resultType="com.security.securitydemo.pojo.Auth">
SELECT * FROM auth WHERE username = #{username} AND password = #{password}
</select>
<select id="byusername" resultType="com.security.securitydemo.pojo.Auth">
SELECT * FROM auth WHERE username = #{username}
</select>
</mapper>
-->pojo包下的Auth实体类
package com.security.securitydemo.pojo;
import lombok.Data;
/**
* 使用 @Data 需要插件和 maven 依赖
*/
@Data
public class Auth {
private Integer ids;
private String username;
private String password;
private String aut;
}
-->mapper包下的AuthMapper类
package com.security.securitydemo.mapper;
import com.security.securitydemo.pojo.Auth;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface AutMapper {
public List<Auth> finall();
public Auth getuser(@Param("username") String username, @Param("password") String password);
public Auth byusername(@Param("username") String username);
}
-->service包下的AuthService类
package com.security.securitydemo.service;
import com.security.securitydemo.mapper.AutMapper;
import com.security.securitydemo.pojo.Auth;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class AuthService implements UserDetailsService {
@Autowired
AutMapper autmapper;
public List<Auth> finall(){
return autmapper.finall();
}
public Auth getuser( String username, String password){
return autmapper.getuser(username, password);
}
/**
* 安全认证 实现 UserDetailsService 接口的方法实现
* 根据用户的 username 来加载用户信息
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据 username 查询出用户信息
Auth auth = autmapper.byusername(username);
if(auth == null){
throw new UsernameNotFoundException("用户名不存在");
}
BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
String newPassword = passwordEncoder.encode(auth.getPassword());//加密
System.out.println("加密密码:" + newPassword);
return new User(auth.getUsername(),newPassword,createAuthority(auth.getAut()));
}
//这里是将数据库的角色分割,构造GrantedAuthority
private List<SimpleGrantedAuthority> createAuthority(String roles) {
String[] roleArray = roles.split(",");
List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
for (String role : roleArray) {
authorityList.add(new SimpleGrantedAuthority(role));
}
return authorityList;
}
}
--->controller包下的Controller控制类
package com.security.securitydemo.controller;
import com.security.securitydemo.pojo.Auth;
import com.security.securitydemo.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
public class DeptController {
@Autowired
AuthService userMapper;
/**
* 登录
* @param request
* @return
*/
@GetMapping("/logins")
public String login(HttpServletRequest request ){
String username = request.getParameter("username");
String password = request.getParameter("password");
//查询用户信息
Auth aut = userMapper.getuser(username,password);
if(aut != null){
System.out.println("登录成功");
return "登录成功";
}else{
System.out.println("登录失败");
return "登录失败";
}
}
/**
* 查询用户所有信息
* @return
*/
@GetMapping("/u")
public List<Auth> getauth(){
List<Auth> auth = userMapper.finall();
return auth;
}
//需要 ADMIN 角色的权限
@GetMapping("/p/s")
public String authAdmin(){
return "admin--权限";
}
//需要 USER 角色的权限
@GetMapping("/a/s")
public String authUser(){
return "user--权限";
}
}
-->config包下的SecurityConfig类
package com.security.securitydemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* Spring Security 配置类.
*
*/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法安全设置
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//***************************数据库验证--------------
@Autowired
private UserDetailsService userDetailsService;
//private AuthService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 使用 BCrypt 加密,密码以明文的方式进行匹配不然会报错
}
/**
* 取出验证信息
* @return
*/
@Bean
public AuthenticationProvider authenticationProvider() {
System.out.println("验证信息----------------");
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder); // 设置密码加密方式
return authenticationProvider;
}
//***************************数据库验证----------
/**
* 自定义配置,定义http安全规则
*
* 数据库角色需要写 ROLE_ADMIN 对应权限认证的 ADMIN
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("认证请求验证----------------");
//认证请求
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/fonts/**", "/index").permitAll() // 都可以访问
.antMatchers("/u/**").permitAll() // 都可以访问
.antMatchers("/p/**").hasRole("ADMIN") // 需要相应的角色才能访问(区分大小写)
.antMatchers("/a/**").hasRole("USER") // 需要相应的角色才能访问
.and()
.formLogin(); //基于Form 表单登录验证
/*.loginPage("/login").failureUrl("/login-error") // 自定义登录界面
.and().exceptionHandling().accessDeniedPage("/403"); // 处理异常,拒绝访问就重定向到 403 页面
*/
}
/**
* 认证信息管理
* @param auth
* @throws Exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
/**
* todo 通过数据库进行查询验证----------------
* 我们需要在 service 层中实现 userDetailsService
*/
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
}
测试
会首先跳到默认登录页面,登录用户信息,获取相应的权限才会访问正常的路径不然就拦截。
拦截
登录
用户名:aaa 密码:aaa
完成