1.准备数据库表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
DROP TABLE IF EXISTS ` permission` ;
CREATE TABLE ` permission` (
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` pname` varchar ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
PRIMARY KEY ( ` id` ) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO ` permission` VALUES ( 1 , '/admin/**' ) ;
INSERT INTO ` permission` VALUES ( 2 , '/user/**' ) ;
INSERT INTO ` permission` VALUES ( 3 , '/dba/**' ) ;
DROP TABLE IF EXISTS ` role` ;
CREATE TABLE ` role` (
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` rname` varchar ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
` rnameZh` varchar ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
PRIMARY KEY ( ` id` ) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO ` role` VALUES ( 1 , 'ROLE_admin' , '管理员' ) ;
INSERT INTO ` role` VALUES ( 2 , 'ROLE_user' , '普通用户' ) ;
INSERT INTO ` role` VALUES ( 3 , 'ROLE_dba' , '数据库管理员' ) ;
DROP TABLE IF EXISTS ` role_permission` ;
CREATE TABLE ` role_permission` (
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` rid` int ( 11 ) NOT NULL ,
` pid` int ( 11 ) NOT NULL ,
PRIMARY KEY ( ` id` ) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO ` role_permission` VALUES ( 1 , 1 , 1 ) ;
INSERT INTO ` role_permission` VALUES ( 2 , 1 , 2 ) ;
INSERT INTO ` role_permission` VALUES ( 3 , 2 , 2 ) ;
INSERT INTO ` role_permission` VALUES ( 4 , 3 , 2 ) ;
INSERT INTO ` role_permission` VALUES ( 5 , 3 , 3 ) ;
INSERT INTO ` role_permission` VALUES ( 6 , 1 , 3 ) ;
DROP TABLE IF EXISTS ` user ` ;
CREATE TABLE ` user ` (
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` username` varchar ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
` password` varchar ( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
` gender` tinyint ( 1 ) NOT NULL DEFAULT 1 ,
` nonLocked` tinyint ( 1 ) NULL DEFAULT 1 ,
` enabled` tinyint ( 1 ) NULL DEFAULT 1 ,
PRIMARY KEY ( ` id` ) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO ` user ` VALUES ( 1 , 'root' , '$2a$10$Z7tAYN0UaT6y.Mg40Ir3QOyz78mp/7jjgaV3KRyuMxIMbodtADH8C' , 0 , 1 , 1 ) ;
INSERT INTO ` user ` VALUES ( 2 , 'admin' , '$2a$10$Z7tAYN0UaT6y.Mg40Ir3QOyz78mp/7jjgaV3KRyuMxIMbodtADH8C' , 1 , 1 , 1 ) ;
INSERT INTO ` user ` VALUES ( 3 , 'user' , '$2a$10$Z7tAYN0UaT6y.Mg40Ir3QOyz78mp/7jjgaV3KRyuMxIMbodtADH8C' , 1 , 1 , 1 ) ;
DROP TABLE IF EXISTS ` user_role` ;
CREATE TABLE ` user_role` (
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` uid` int ( 11 ) NOT NULL ,
` rid` int ( 11 ) NOT NULL ,
PRIMARY KEY ( ` id` ) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO ` user_role` VALUES ( 1 , 1 , 1 ) ;
INSERT INTO ` user_role` VALUES ( 2 , 1 , 2 ) ;
INSERT INTO ` user_role` VALUES ( 3 , 2 , 2 ) ;
INSERT INTO ` user_role` VALUES ( 4 , 3 , 2 ) ;
INSERT INTO ` user_role` VALUES ( 5 , 1 , 3 ) ;
SET FOREIGN_KEY_CHECKS = 1 ;
2.配置代码
1.application.properties
server.port=8080
spring.application.name=khm_security
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
logging.level.com.example.spring_security.mapper=debug
2.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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.khm</groupId>
<artifactId>spring_security01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring_security01</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</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>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
3.Java代码
1.SecurityConfig
package org. khm. config ;
import org. khm. service. UserService ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. context. annotation. Bean ;
import org. springframework. context. annotation. Configuration ;
import org. springframework. security. config. annotation. ObjectPostProcessor ;
import org. springframework. security. config. annotation. authentication. builders. AuthenticationManagerBuilder ;
import org. springframework. security. config. annotation. web. builders. HttpSecurity ;
import org. springframework. security. config. annotation. web. builders. WebSecurity ;
import org. springframework. security. config. annotation. web. configuration. EnableWebSecurity ;
import org. springframework. security. config. annotation. web. configuration. WebSecurityConfigurerAdapter ;
import org. springframework. security. crypto. bcrypt. BCryptPasswordEncoder ;
import org. springframework. security. crypto. password. PasswordEncoder ;
import org. springframework. security. web. access. intercept. FilterSecurityInterceptor ;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;
@Autowired
MyAccessDecisionManager myAccessDecisionManager;
@Bean
PasswordEncoder passwordEncoder ( ) {
return new BCryptPasswordEncoder ( ) ;
}
@Autowired
UserService userService;
@Override
protected void configure ( AuthenticationManagerBuilder auth) throws Exception {
auth. userDetailsService ( userService) ;
}
@Override
public void configure ( WebSecurity web) throws Exception {
web. ignoring ( ) . antMatchers ( "/index" , "/login" ) ;
}
@Override
protected void configure ( HttpSecurity http) throws Exception {
http. authorizeRequests ( )
. withObjectPostProcessor ( new ObjectPostProcessor < FilterSecurityInterceptor > ( ) {
@Override
public < O extends FilterSecurityInterceptor > O postProcess ( O o) {
o. setSecurityMetadataSource ( myFilterInvocationSecurityMetadataSource) ;
o. setAccessDecisionManager ( myAccessDecisionManager) ;
return o;
}
} )
. anyRequest ( ) . authenticated ( )
. and ( )
. formLogin ( )
. loginPage ( "/login" )
. loginProcessingUrl ( "/doLogin" )
. successHandler ( ( req, resp, authentication) -> {
String username = req. getParameter ( "username" ) ;
String password = req. getParameter ( "password" ) ;
System . out. println ( authentication. getPrincipal ( ) ) ;
System . out. println ( username) ;
System . out. println ( password) ;
} )
. permitAll ( )
. and ( )
. csrf ( ) . disable ( ) ;
}
}
2.MyFilterInvocationSecurityMetadataSource.java
package org. khm. config ;
import org. khm. model. Permission ;
import org. khm. model. Role ;
import org. khm. service. PermissionService ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. security. access. ConfigAttribute ;
import org. springframework. security. access. SecurityConfig ;
import org. springframework. security. web. FilterInvocation ;
import org. springframework. security. web. access. intercept. FilterInvocationSecurityMetadataSource ;
import org. springframework. stereotype. Component ;
import org. springframework. util. AntPathMatcher ;
import java. util. Collection ;
import java. util. List ;
@Component
public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
@Autowired
PermissionService permissionService;
@Override
public Collection < ConfigAttribute > getAttributes ( Object o) throws IllegalArgumentException {
FilterInvocation filterInvocation = ( FilterInvocation ) o;
String requestUrl = filterInvocation. getRequestUrl ( ) ;
List < Permission > permissions = permissionService. getPermissionRoles ( ) ;
AntPathMatcher antPathMatcher = new AntPathMatcher ( ) ;
for ( Permission permission : permissions) {
if ( antPathMatcher. match ( permission. getPname ( ) , requestUrl) ) {
List < Role > roles = permission. getRoles ( ) ;
String [ ] arr = new String [ roles. size ( ) ] ;
for ( int i = 0 ; i < arr. length; i++ ) {
arr[ i] = roles. get ( i) . getRname ( ) ;
}
return SecurityConfig . createList ( arr) ;
}
}
return SecurityConfig . createList ( "ROLE_login" ) ;
}
@Override
public Collection < ConfigAttribute > getAllConfigAttributes ( ) {
return null ;
}
@Override
public boolean supports ( Class < ? > aClass) {
return true ;
}
}
3.MyAccessDecisionManager.java
package org. khm. config ;
import org. springframework. security. access. AccessDecisionManager ;
import org. springframework. security. access. AccessDeniedException ;
import org. springframework. security. access. ConfigAttribute ;
import org. springframework. security. authentication. AnonymousAuthenticationToken ;
import org. springframework. security. authentication. InsufficientAuthenticationException ;
import org. springframework. security. core. Authentication ;
import org. springframework. security. core. GrantedAuthority ;
import org. springframework. stereotype. Component ;
import java. util. Collection ;
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide ( Authentication authentication, Object o, Collection < ConfigAttribute > collection) throws AccessDeniedException , InsufficientAuthenticationException {
for ( ConfigAttribute configAttribute : collection) {
String attribute = configAttribute. getAttribute ( ) ;
if ( "ROLE_login" . equals ( attribute) ) {
if ( authentication instanceof AnonymousAuthenticationToken ) {
throw new AccessDeniedException ( "用户未登录" ) ;
}
return ;
}
Collection < ? extends GrantedAuthority > authorities = authentication. getAuthorities ( ) ;
for ( GrantedAuthority authority : authorities) {
if ( authority. getAuthority ( ) . equals ( attribute) ) {
return ;
}
}
}
throw new AccessDeniedException ( "权限不足" ) ;
}
@Override
public boolean supports ( ConfigAttribute configAttribute) {
return true ;
}
@Override
public boolean supports ( Class < ? > aClass) {
return true ;
}
}
4.PermissionService.java
package org. khm. service ;
import org. khm. mapper. PermissionMapper ;
import org. khm. model. Permission ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Service ;
import org. springframework. transaction. annotation. Transactional ;
import java. util. List ;
@Service
@Transactional
public class PermissionService {
@Autowired
PermissionMapper permissionMapper;
public List < Permission > getPermissionRoles ( ) {
return permissionMapper. getPermissionRoles ( ) ;
}
}
5.UserService.java
package org. khm. service ;
import org. khm. mapper. UserMapper ;
import org. khm. model. Role ;
import org. khm. model. User ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. security. core. userdetails. UserDetails ;
import org. springframework. security. core. userdetails. UserDetailsService ;
import org. springframework. security. core. userdetails. UsernameNotFoundException ;
import org. springframework. stereotype. Service ;
import java. util. List ;
@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername ( String username) throws UsernameNotFoundException {
User user = userMapper. findUserByUserName ( username) ;
if ( user == null ) {
throw new UsernameNotFoundException ( "没有此用户" ) ;
}
List < Role > roles = userMapper. findRoleByUserId ( user. getId ( ) ) ;
user. setRoles ( roles) ;
return user;
}
}
6.PermissionMapper
package org. khm. mapper ;
import org. khm. model. Permission ;
import java. util. List ;
public interface PermissionMapper {
List < Permission > getPermissionRoles ( ) ;
}
<?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 = " org.khm.mapper.PermissionMapper" >
< resultMap id = " BaseResultMap" type = " org.khm.model.Permission" >
< id column = " pid" property = " id" > </ id>
< result column = " pname" property = " pname" > </ result>
< collection property = " roles" ofType = " org.khm.model.Role" >
< id column = " rid" property = " id" > </ id>
< result column = " rname" property = " rname" > </ result>
< result column = " rnameZh" property = " rnameZh" > </ result>
</ collection>
</ resultMap>
< select id = " getPermissionRoles" resultMap = " BaseResultMap" >
select p.id as pid, pname, r.id as rid, rname, rnameZh
from role r
join role_permission rp
on r.id = rp.rid
join permission p
on rp.pid = p.id
</ select>
</ mapper>
7.UserMapper
package org. khm. mapper ;
import org. khm. model. Role ;
import org. khm. model. User ;
import java. util. List ;
public interface UserMapper {
User findUserByUserName ( String username) ;
List < Role > findRoleByUserId ( Integer id) ;
}
<?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 = " org.khm.mapper.UserMapper" >
< select id = " findUserByUserName" resultType = " org.khm.model.User" >
select *
from user
where username = #{username}
</ select>
< select id = " findRoleByUserId" resultType = " org.khm.model.Role" >
select *
from role
where id in (select rid from user_role where uid = #{id})
</ select>
</ mapper>
8.Controller.java
package org. khm. controller ;
import org. springframework. web. bind. annotation. RequestMapping ;
import org. springframework. web. bind. annotation. RestController ;
@RestController
public class UserController {
@RequestMapping ( "/home" )
public String hello ( ) {
return "HOME" ;
}
@RequestMapping ( "/index" )
public String index ( ) {
return "首页" ;
}
@RequestMapping ( "/login" )
public String login ( ) {
return "请登录" ;
}
@RequestMapping ( "/doLogin" )
public String loginUser ( ) {
return "你好" ;
}
@RequestMapping ( "/admin/hello" )
public String loginAdmin ( ) {
return "你好,管理员" ;
}
@RequestMapping ( "/user/hello" )
public String loginPerson ( ) {
return "你好,用户" ;
}
@RequestMapping ( "/dba/hello" )
public String loginDBA ( ) {
return "你好,DBA" ;
}
}