Spring Security 6 基于数据库实现登录认证
在现代 web 应用程序中,安全性是必须要考虑的问题。Spring Security 提供了一套强大的认证和授权框架,允许我们轻松实现基于数据库的登录认证。本文将介绍如何使用 Spring Security 6 和 JPA 实现用户的登录认证。
项目结构
我们将基于 Spring Boot 创建一个简单的 Spring Security 项目,项目结构如下:
src/main/java/com/example/security/
├── SecurityApplication.java
├── config/
│ └── SecurityConfig.java
├── controller/
│ └── LoginController.java
├── entity/
│ └── User.java
├── repository/
│ └── UserRepository.java
└── service/
└── UserDetailsServiceImpl.java
1. 添加依赖
在 pom.xml
文件中添加 Spring Security 和 JPA 的依赖:
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 数据库(用于开发和测试) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 其他依赖 -->
</dependencies>
2. 创建实体类
我们创建一个简单的 User
实体类,表示用户信息。
package com.example.security.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// getters and setters
}
3. 创建 JPA Repository
接下来,我们创建一个 UserRepository
接口,用于操作数据库中的用户信息。
package com.example.security.repository;
import com.example.security.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
4. 实现 UserDetailsService
实现 UserDetailsService
接口,加载用户的详细信息。
package com.example.security.service;
import com.example.security.entity.User;
import com.example.security.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
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;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return org.springframework.security.core.userdetails.User.withUsername(user.getUsername())
.password(user.getPassword())
.roles("USER") // 默认角色
.build();
}
}
5. 配置 Spring Security
在 SecurityConfig
中配置 Spring Security 的基本设置。
package com.example.security.config;
import com.example.security.service.UserDetailsServiceImpl;
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.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
6. 创建登录控制器
创建一个控制器来处理登录请求:
package com.example.security.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login"; // 返回登录页面视图
}
}
7. 创建登录页面
最后,我们需要创建一个简单的登录页面 login.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<form action="/login" method="post">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username"/>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password"/>
</div>
<div>
<button type="submit">登录</button>
</div>
</form>
</body>
</html>
总结
至此,我们使用 Spring Security 6 实现了基于数据库的用户登录认证。在实际应用中,我们需要确保用户的密码是加密存储的,并且可以在注册时对密码进行加密。
这种实现方式具有一定的灵活性,可以根据需求拓展更多功能,例如角色权限控制、记住我功能等。希望本文能对您使用 Spring Security 提供一些帮助和启发!