目录
一、用户认证
1、设置登录系统的账号、密码
方式一:通过配置文件
方式二:通过配置类
方式三:自定义编写实现类(常用)
2、通过查询数据库完成登录认证
技术点:
第一步:引入MybatisPlus相关依赖
第二步:创建数据库和数据库表
第三步:创建实体类
第四步:创建mapper,并创建UsersMapper接口
第五步:在MyUserDetailsService中调用mapper里面的方法,通过查询数据库进行用户认证
第六步:在启动类(或者配置类)添加@MapperScan注解
第七步:在配置文件application.properties中配置数据库
第八步:访问测试
3、自定义用户登录页面
第一步:修改配置类MySecurityConfig
第二步:创建login.html页面
第三步:在TestController添加index
第四步:访问测试
一、用户认证
1、设置登录系统的账号、密码
方式一:通过配置文件
在 application.properties里面进行配置:
server.port=8111
spring.security.user.name=zibo
spring.security.user.password=123456
方式二:通过配置类
代码演示:
package com.zibo.studyspringsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 对密码进行加密
        String password = new BCryptPasswordEncoder().encode("123456");
        // 设置账号和密码以及角色
        auth.inMemoryAuthentication().withUser("zibo").password(password).roles("admin");
    }
}访问测试:

错误解决(修改配置类):
package com.zibo.studyspringsecurity.config;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 对密码进行加密
        String password = new BCryptPasswordEncoder().encode("123456");
        // 设置账号和密码以及角色
        auth.inMemoryAuthentication().withUser("zibo").password(password).roles("admin");
    }
    // 注入 PasswordEncoder 类到 spring 容器中
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}再次访问测试:

方式三:自定义编写实现类(常用)
概述:
前面的两种方法都不常用,实际项目中肯定是从数据库查询账号和密码;
步骤:
第一步:创建配置类,设置使用哪个userDetailsService实现类;
第二步:编写实现类,返回User对象,User对象有用户名、密码以及操作权限;
第一步代码演示:
package com.zibo.studyspringsecurity.config;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    // 注入 PasswordEncoder 类到 spring 容器中
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}第二步代码演示:
package com.zibo.studyspringsecurity.service;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        // 此处仅作演示,实际项目中肯定是从数据库查询的
        // 上面的参数String s是表单提取的用户名,我们可以通过用户名去数据库查数据
        // 查到了返回,查不到就进行抛出异常或者进行页面跳转或者提示等操作
        // 咱们在这里打印一下s看一下
        System.out.println("表单提交的用户名是:" + s);
        // 手动创建一个Collection<? extends GrantedAuthority> authorities 权限集合
        // 实际项目中是从数据库查询的
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User("zibo",new BCryptPasswordEncoder().encode("123456"),auths); // 此处的auths不允许为空
    }
}访问测试:

2、通过查询数据库完成登录认证
技术点:
整合MybatisPlus完成查询数据库的操作;
第一步:引入MybatisPlus相关依赖
<?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.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zibo</groupId>
    <artifactId>studyspringsecurity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>studyspringsecurity</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--改成web工程-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--添加spring-security依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--lombok 用来简化实体类-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
第二步:创建数据库和数据库表
(下面一些数据库表是以后需要用到的,现在此统一创建出来)
创建数据库:

创建用户表:
CREATE TABLE users ( id BIGINT PRIMARY KEY auto_increment, username VARCHAR ( 20 ) UNIQUE NOT NULL, PASSWORD VARCHAR ( 100 ) );添加用户数据:
INSERT INTO users
VALUES
	( 1, '张三', '123456' );
INSERT INTO users
VALUES
	( 2, '李四', '123456' );创建角色表:
CREATE TABLE role ( id BIGINT PRIMARY KEY auto_increment, NAME VARCHAR ( 20 ) );插入角色数据:
insert into role values(1,'管理员');
insert into role values(2,'普通用户');创建用户_角色表:
CREATE TABLE role_user ( uid BIGINT, rid BIGINT );插入用户_角色数据:
insert into role_user values(1,1);
insert into role_user values(2,2);创建菜单表:
CREATE TABLE menu ( id BIGINT PRIMARY KEY auto_increment, NAME VARCHAR ( 20 ), url VARCHAR ( 100 ), parentid BIGINT, permission VARCHAR ( 20 ) );插入菜单数据:
insert into menu values(1,'系统管理','',0,'menu:system');
insert into menu values(2,'用户管理','',0,'menu:user');创建菜单_角色表:
CREATE TABLE role_menu ( mid BIGINT, rid BIGINT );插入菜单_角色数据:
insert into role_menu values(1,1);
insert into role_menu values(2,1);
insert into role_menu values(2,2);
第三步:创建实体类
创建entity包,并创建Users实体类:
package com.zibo.studyspringsecurity.entity;
import lombok.Data;
@Data
public class Users {
    private Integer id;
    private String username;
    private String password;
}
第四步:创建mapper,并创建UsersMapper接口
package com.zibo.studyspringsecurity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zibo.studyspringsecurity.entity.Users;
import org.springframework.stereotype.Repository;
@Repository // 不加会提示错误,但可以运行
public interface UsersMapper extends BaseMapper<Users> {
}
第五步:在MyUserDetailsService中调用mapper里面的方法,通过查询数据库进行用户认证
package com.zibo.studyspringsecurity.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zibo.studyspringsecurity.entity.Users;
import com.zibo.studyspringsecurity.mapper.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    private UsersMapper usersMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 调用usersMapper方法,根据用户名查询数据库
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        // 根据用户名查询
        wrapper.eq("username",username);
        Users users = usersMapper.selectOne(wrapper);
        if(users==null){ // 数据库里面没有此用户名,认证失败
            throw new UsernameNotFoundException("用户名不存在!");
        }
        // 手动创建一个Collection<? extends GrantedAuthority> authorities 角色权限集合
        // 实际项目中是从数据库查询的
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        // 返回从数据库中查询到的账号、密码和角色信息
        return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
    }
}
第六步:在启动类(或者配置类)添加@MapperScan注解
package com.zibo.studyspringsecurity;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.zibo.studyspringsecurity.mapper")
public class StudyspringsecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudyspringsecurityApplication.class, args);
    }
}
第七步:在配置文件application.properties中配置数据库
server.port=8111
# 设置security登录的账号密码
# spring.security.user.name=zibo
# spring.security.user.password=123456
# mysql 数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 
spring.datasource.url=jdbc:mysql://localhost:3306/spring_security?serverTimezone=GMT%2B8 
spring.datasource.username=root
spring.datasource.password=root
第八步:访问测试
用户名:张三;密码:123456;

3、自定义用户登录页面
第一步:修改配置类MySecurityConfig
package com.zibo.studyspringsecurity.config;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    // 注入 PasswordEncoder 类到 spring 容器中
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin() // 自定义自己编写的登录页面
            // 登录页面设置
            .loginPage("/login.html")
            // 登录访问的路径,提交到的controller,不需要自己写
            .loginProcessingUrl("/user/login")
            // 登陆成功之后要跳转到的路径
            .defaultSuccessUrl("/test/index").permitAll()
            // 设置哪些路径不需要登陆就可以访问
            .and().authorizeRequests().antMatchers("/","/test/hello","/user/login").permitAll()
            .anyRequest().authenticated()
            .and().csrf().disable(); // 关闭csrf防护
    }
}
第二步:创建login.html页面
在resources目录下创建static目录,并创建login.html,name必须是username和password;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post" action="/user/login">
        用户名:<input type="text" name="username"/>
        密码:<input type="text" name="password"/>
        <input type="submit" value="登录"/>
    </form>
</body>
</html>
第三步:在TestController添加index
package com.zibo.studyspringsecurity.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping("/hello")
    public String hello(){
        return "Hello Spring Security!";
    }
    @GetMapping("/index")
    public String index(){
        return "登录成功!";
    }
}
第四步:访问测试
访问http://localhost:8111/test/hello

访问http://localhost:8111/test/index

登录测试:











