天天看點

springboot學習系列九:springboot內建spring security

目錄

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預設的登入界面如下所示。

springboot學習系列九:springboot內建spring security

登入成功界面,如下所示。

springboot學習系列九:springboot內建spring security

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

springboot學習系列九:springboot內建spring security