跳到主要内容

Spring 用户存储

介绍

在 Spring Security 中,用户存储是用于管理用户认证信息(如用户名、密码和角色)的核心组件。Spring Security 提供了多种用户存储的实现方式,包括内存存储、JDBC 存储和自定义用户存储。本文将逐步介绍这些用户存储的实现方式,并通过实际案例展示其应用场景。

内存用户存储

内存用户存储是最简单的用户存储方式,适用于开发环境或小型应用。它允许我们在代码中直接定义用户信息。

代码示例

以下是一个使用内存用户存储的配置示例:

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("{noop}password") // {noop} 表示不加密密码
.roles("USER")
.and()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN");
}
}

解释

  • auth.inMemoryAuthentication():启用内存用户存储。
  • withUser("user"):定义一个用户名为 "user" 的用户。
  • password("{noop}password"):设置用户密码为 "password",{noop} 表示不加密密码。
  • roles("USER"):为用户分配 "USER" 角色。
备注

在实际生产环境中,不建议使用内存用户存储,因为它无法持久化用户数据。

JDBC 用户存储

JDBC 用户存储通过数据库来管理用户信息,适用于需要持久化用户数据的应用。

代码示例

以下是一个使用 JDBC 用户存储的配置示例:

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private DataSource dataSource;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?")
.authoritiesByUsernameQuery("SELECT username, authority FROM authorities WHERE username = ?");
}
}

解释

  • auth.jdbcAuthentication():启用 JDBC 用户存储。
  • dataSource(dataSource):指定数据源。
  • usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?"):定义查询用户信息的 SQL 语句。
  • authoritiesByUsernameQuery("SELECT username, authority FROM authorities WHERE username = ?"):定义查询用户权限的 SQL 语句。
提示

确保数据库中存在 usersauthorities 表,并且表结构与查询语句匹配。

自定义用户存储

自定义用户存储允许我们根据特定需求实现用户存储逻辑,通常用于集成外部用户管理系统。

代码示例

以下是一个自定义用户存储的实现示例:

java
@Service
public class CustomUserDetailsService 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 new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getAuthorities()
);
}
}

解释

  • UserDetailsService:Spring Security 提供的接口,用于加载用户信息。
  • loadUserByUsername(String username):根据用户名加载用户信息。
  • UserRepository:自定义的用户数据访问接口。
警告

确保自定义用户存储的实现符合 Spring Security 的要求,特别是 UserDetails 的创建。

实际案例

假设我们正在开发一个在线书店应用,需要为不同用户分配不同的权限。我们可以使用 JDBC 用户存储来管理用户信息,并通过自定义用户存储集成外部用户管理系统。

场景描述

  • 普通用户可以浏览书籍和下单。
  • 管理员用户可以管理书籍和订单。

实现步骤

  1. 创建 usersauthorities 表。
  2. 配置 JDBC 用户存储。
  3. 实现自定义用户存储以集成外部用户管理系统。

总结

Spring Security 提供了多种用户存储的实现方式,包括内存存储、JDBC 存储和自定义用户存储。每种方式都有其适用场景,开发者可以根据实际需求选择合适的用户存储方式。

附加资源

练习

  1. 尝试在内存用户存储中添加多个用户,并测试其认证功能。
  2. 使用 JDBC 用户存储实现一个简单的用户管理系统。
  3. 实现一个自定义用户存储,集成外部用户管理系统。