spring-security——web权限方案:用户认证

本文最后更新于:2022年5月20日 下午

摘要:Spring Security web权限认证的三种方案。针对自定义编写实现类方式,详细介绍了使用Mybatis-Plus访问数据库完成用户认证。

Spring Security web权限方案

Spring Security中的web权限方案分为认证和授权。

设置登录的用户名和密码

  1. 通过配置文件
  2. 通过配置类
  3. 自定义编写实现类

配置文件方式

在【application.properties】中设置

1
2
spring.security.user.name=root
spring.security.user.password=root

配置类方式

  • 新建一个配置类【SecurityConfig】,并在类上加【@Configuration】注解

  • 继承【WebSecurityConfigurerAdapter】,重写configure方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.shg.securitydemo.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;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
* @author: shg
* @create: 2022-05-15 4:28 下午
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("root");
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder)
.withUser("root")
.password(password)
.roles("admin");
}
}

自定义编写实现类方式

自定义实现类设置

  • 创建配置类,设置使用哪个UserDetailService实现类
  • 编写实现类,返回User对象,User对象有用户名密码和操作权限
自定义方式开发步骤
  1. 创建配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.shg.securitydemo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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;

/**
* @author: shg
* @create: 2022-05-15 4:52 下午
*/
@Configuration
public class SecurityConfig1 extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
}

  1. 编写【UserDetailsService】的实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.shg.securitydemo.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;

/**
* @author: shg
* @create: 2022-05-15 5:02 下午
*/
@Service(value = "userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User("root",
new BCryptPasswordEncoder().encode("root"),
authorities);
}
}

查询数据库完成用户认证

整合Mybatis-Plus完成数据库操作

  1. 引入相关依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>

<!-- lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
  1. 创建数据库和数据库表

创建一个user表结构如下,包含id、name、password三个字段

user表结构
  1. 创建user表对应实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.shg.securitydemo.entity;

import lombok.Data;

/**
* @author: shg
* @create: 2022-05-15 5:32 下午
*/
@Data
public class User {
private int id;
private String name;
private String password;
}

  1. 整合Mybaist-Plus,创建接口【UserMapper】,继承【BaseMapper】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.shg.securitydemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shg.securitydemo.entity.User;
import org.apache.ibatis.annotations.Mapper;

/**
* @author: shg
* @create: 2022-05-15 5:36 下午
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

  1. 在【UserDetailsService】实现类中查询数据库进行认证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.shg.securitydemo.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shg.securitydemo.entity.User;
import com.shg.securitydemo.mapper.UserMapper;
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.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;

/**
* @author: shg
* @create: 2022-05-15 5:48 下午
*/
@Service(value = "userDetailsService1")
public class MyUserDetailsService1 implements UserDetailsService {

@Autowired
private UserMapper userMapper;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 调用userMapper中的方法,根据用户名查询数据库
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 设置查询条件
wrapper.eq("name", username);
User user = userMapper.selectOne(wrapper);
// 判断是否查到用户
if (user == null) { // 数据库没有用户名,认证失败
throw new UsernameNotFoundException("用户名不存在!");
}
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("role");

return new org.springframework.security.core.userdetails.User(user.getName(),
new BCryptPasswordEncoder().encode(user.getPassword()),
authorities);
}
}

  1. 创建配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.shg.securitydemo.config;

import org.springframework.beans.factory.annotation.Autowired;
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;

/**
* @author: shg
* @create: 2022-05-15 7:45 下午
*/
@Configuration
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
}

  1. 在启动类【SecurityDemoApplication】中加入@MapperScan注解指定扫描包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.shg.securitydemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(value = {"com.shg.securitydemo.mapper"})
public class SecurityDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityDemoApplication.class, args);
}
}

  1. 在【application.properties】中配置数据库连接
1
2
3
4
5
# 配置数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

自定义登录页面

  1. 在配置类中重写configure(HttpSecurity http)方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.shg.securitydemo.config;

import org.springframework.beans.factory.annotation.Autowired;
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;

/**
* @author: shg
* @create: 2022-05-15 7:45 下午
*/
@Configuration
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 自定义自己编写的登录页面
.loginPage("/login.html")
.loginProcessingUrl("/user/login") // 登录访问路径
.defaultSuccessUrl("/test/index").permitAll() // 登录成功后跳转页面
.and().authorizeRequests()
.antMatchers("/", "/test/hello", "/user/login").permitAll() // 设置哪些路径可以直接访问不需要认证
.anyRequest().authenticated()
.and().csrf().disable(); // 关闭csrf防护
}
}

  1. 编写一个login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/user/login" method="post">
用户名:<input type="text" name="username">
<br />
密码:<input type="text" name="password">
<br />
<input type="submit" value="login">
</form>
</body>
</html>
  1. 在【TestController】中定义一个访问首页的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.shg.securitydemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author: shg
* @create: 2022-05-14 7:00 下午
*/
@RestController
@RequestMapping("/test")
public class TestController {

@GetMapping("hello")
public String hello() {
return "hello security";
}

@GetMapping("/index")
public String index() {
return "index";
}

}


spring-security——web权限方案:用户认证
https://shgang97.github.io/posts/spring-security-web-cd277d24c6fd/
作者
shgang
发布于
2022年5月15日
更新于
2022年5月20日
许可协议