目錄
Spring security簡介
pom.xml
application.yml
測試執行個體
Spring security簡介
Spring security是spring下的一個功能強大且可高度自定義的身份驗證和通路控制(授權)架構。其核心功能主要包括認證(解決你是誰的問題)、授權(你能夠做什麼的問題)、攻擊防護(解決身份僞造的問題)等。與Apache shiro安全架構相比,其更加複雜、“重”。
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.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-core</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 8090
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: root
password: 123456
main:
allow-bean-definition-overriding: true #當遇到同樣名字的時候,是否允許覆寫注冊
#指定mybatis映射檔案的位址 mapper-locations為mapper資源檔案的路徑,type-aliases-package為dao層接口檔案存放的目錄
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.mapper
sql
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', 'ROLE_ADMIN');
INSERT INTO `sys_role` VALUES ('2', 'ROLE_USER');
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` varchar(32) NOT NULL COMMENT '主鍵',
`name` varchar(10) DEFAULT NULL COMMENT '使用者名',
`password` varchar(32) DEFAULT NULL COMMENT '密碼',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', '張三', '654321');
INSERT INTO `sys_user` VALUES ('2', '李四', '123456');
INSERT INTO `sys_user` VALUES ('3', '王麻子', '654321');
INSERT INTO `sys_user` VALUES ('4', '劉十', '123456');
-- ----------------------------
-- Table structure for sys_user_role_rel
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role_rel`;
CREATE TABLE `sys_user_role_rel` (
`user_id` varchar(255) DEFAULT NULL,
`role_id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of sys_user_role_rel
-- ----------------------------
INSERT INTO `sys_user_role_rel` VALUES ('1', '1');
INSERT INTO `sys_user_role_rel` VALUES ('2', '2');
INSERT INTO `sys_user_role_rel` VALUES ('3', '2');
INSERT INTO `sys_user_role_rel` VALUES ('4', '1');
測試執行個體
(1)entity
package com.example.demo.entity;
import java.io.Serializable;
public class SysUser implements Serializable {
private String id;
private String name;
private String password;
public SysUser() {
}
public SysUser(String id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
public String getId() {
return id;
}
public void setId(String 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;
}
@Override
public String toString() {
return "SysUser{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.example.demo.entity;
import java.io.Serializable;
public class SysRole implements Serializable {
private String id;
private String name;
public SysRole() {
}
public SysRole(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "SysRole{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
package com.example.demo.entity;
import java.io.Serializable;
public class SysUserRoleRel implements Serializable {
private String userId;
private String roleId;
public SysUserRoleRel() {
}
public SysUserRoleRel(String userId, String roleId) {
this.userId = userId;
this.roleId = roleId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
@Override
public String toString() {
return "SysUserRoleRel{" +
"userId='" + userId + '\'' +
", roleId='" + roleId + '\'' +
'}';
}
}
(2)mapper
package com.example.demo.mapper;
import com.example.demo.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SysUserMapper {
public SysUser findByUserName(@Param("userName") String userName);
}
<?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.example.demo.mapper.SysUserMapper">
<resultMap id="BaseResultMap" type="com.example.demo.entity.SysUser">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="password" jdbcType="VARCHAR" property="password" />
</resultMap>
<sql id="Base_Column_List">
id,name,password
</sql>
<select id="findByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"></include>
from sys_user where name = #{userName}
</select>
</mapper>
package com.example.demo.mapper;
import com.example.demo.entity.SysRole;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SysRoleMapper {
public SysRole findRoleById(@Param("id")String 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="com.example.demo.mapper.SysRoleMapper">
<resultMap id="BaseResultMap" type="com.example.demo.entity.SysRole">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
</resultMap>
<sql id="Base_Column_List">
id,name
</sql>
<select id="findRoleById" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"></include>
from sys_role where id = #{id}
</select>
</mapper>
package com.example.demo.mapper;
import com.example.demo.entity.SysUserRoleRel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysUserRoleRelMapper {
public List<SysUserRoleRel> findByUserId(@Param("userId")String userId);
}
<?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.example.demo.mapper.SysUserRoleRelMapper">
<resultMap id="BaseResultMap" type="com.example.demo.entity.SysUserRoleRel">
<id column="user_id" jdbcType="VARCHAR" property="userId" />
<result column="role_id" jdbcType="VARCHAR" property="roleId" />
</resultMap>
<sql id="Base_Column_List">
user_id,role_id
</sql>
<select id="findByUserId" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"></include>
from sys_user_role_rel where user_id = #{userId}
</select>
</mapper>
(3)service
package com.example.demo.service;
import com.example.demo.entity.SysUser;
public interface SysUserService {
public SysUser findByUserName(String userName);
}
package com.example.demo.service.impl;
import com.example.demo.entity.SysUser;
import com.example.demo.mapper.SysUserMapper;
import com.example.demo.service.SysUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class SysUserServiceImpl implements SysUserService {
@Resource
private SysUserMapper sysUserMapper;
@Override
public SysUser findByUserName(String userName) {
return sysUserMapper.findByUserName(userName);
}
}
package com.example.demo.service;
import com.example.demo.entity.SysRole;
public interface SysRoleService {
public SysRole findRoleById(String id);
}
package com.example.demo.service.impl;
import com.example.demo.entity.SysRole;
import com.example.demo.mapper.SysRoleMapper;
import com.example.demo.service.SysRoleService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class SysRoleServiceImpl implements SysRoleService {
@Resource
private SysRoleMapper sysRoleMapper;
@Override
public SysRole findRoleById(String id) {
return sysRoleMapper.findRoleById(id);
}
}
package com.example.demo.service;
import com.example.demo.entity.SysUserRoleRel;
import java.util.List;
public interface SysUserRoleRelService {
public List<SysUserRoleRel> findByUserId(String userId);
}
package com.example.demo.service.impl;
import com.example.demo.entity.SysUserRoleRel;
import com.example.demo.mapper.SysUserRoleRelMapper;
import com.example.demo.service.SysUserRoleRelService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class SysUserRoleRelServiceImpl implements SysUserRoleRelService {
@Resource
private SysUserRoleRelMapper sysUserRoleRelMapper;
@Override
public List<SysUserRoleRel> findByUserId(String userId) {
return sysUserRoleRelMapper.findByUserId(userId);
}
}
(4)exception
package com.example.demo.exception;
public class BusinessException extends RuntimeException{
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
}
(5)spring security
package com.example.demo.service;
import com.example.demo.entity.SysUser;
import com.example.demo.entity.SysUserRoleRel;
import com.example.demo.exception.BusinessException;
import org.springframework.security.core.GrantedAuthority;
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.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
public class CustomUserService implements UserDetailsService {
@Resource
private SysUserService sysUserService;
@Resource
private SysRoleService sysRoleService;
@Resource
private SysUserRoleRelService sysUserRoleRelService;
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
SysUser sysUser = sysUserService.findByUserName(name);
if(sysUser == null){
throw new BusinessException("使用者不存在");
}
List<SysUserRoleRel> sysUserRoleRelList = sysUserRoleRelService.findByUserId(sysUser.getId());
System.out.println("輸出結果看一下:"+sysUserRoleRelList);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
if(sysUserRoleRelList != null && sysUserRoleRelList.size() > 0 ){
for (SysUserRoleRel rel:sysUserRoleRelList) {
String roleName = sysRoleService.findRoleById(rel.getRoleId()).getName();
authorities.add(new SimpleGrantedAuthority(roleName));
}
}
return new User(sysUser.getName(),sysUser.getPassword(),authorities);
}
}
package com.example.demo.security;
import com.example.demo.service.CustomUserService;
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.authentication.builders.AuthenticationManagerBuilder;
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;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public CustomUserService customUserService(){
return new CustomUserService();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().failureUrl("/login?error").defaultSuccessUrl("/sysUser/test").permitAll();
super.configure(http);
}
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService()).passwordEncoder(new MyPasswordEncoder());
super.configure(auth);
}
}
package com.example.demo.security;
import org.springframework.security.crypto.password.PasswordEncoder;
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
}
(5)測試驗證
啟動項目,spring security預設的登入界面如下所示。

登入成功界面,如下所示。
登入不存在使用者界面,如下圖所示。