目录

一、用户认证

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");
    }
}

访问测试:

【Spring Security】003-Spring Security web权限方案(1):用户认证_mybatis

错误解决(修改配置类):

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();
    }
}

再次访问测试:

【Spring Security】003-Spring Security web权限方案(1):用户认证_数据库_02

 

方式三:自定义编写实现类(常用)

概述:

前面的两种方法都不常用,实际项目中肯定是从数据库查询账号和密码;

步骤:

第一步:创建配置类,设置使用哪个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不允许为空
    }
}

访问测试:

【Spring Security】003-Spring Security web权限方案(1):用户认证_spring boot_03

 

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>

 

第二步:创建数据库和数据库表

(下面一些数据库表是以后需要用到的,现在此统一创建出来)

创建数据库:

【Spring Security】003-Spring Security web权限方案(1):用户认证_mybatis_04

创建用户表:

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;

【Spring Security】003-Spring Security web权限方案(1):用户认证_mybatis_05

 

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

【Spring Security】003-Spring Security web权限方案(1):用户认证_mybatis_06

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

【Spring Security】003-Spring Security web权限方案(1):用户认证_spring_07

登录测试:

【Spring Security】003-Spring Security web权限方案(1):用户认证_spring_08