如何基于Django创建的PostgreSQL用户表实现Spring Boot+Keycloak认证?
实现Spring Boot + Keycloak认证并对接Django的PostgreSQL用户表
第一步:配置Keycloak对接现有PostgreSQL用户/角色表
Keycloak默认使用自带数据库,需要修改配置让它读取Django创建的用户(如auth_user)和角色关联表(如auth_group、auth_user_groups)。
1. 配置PostgreSQL数据源
传统WildFly版本(Keycloak 16及以下)
修改standalone.xml,添加PostgreSQL数据源:
<datasource jndi-name="java:jboss/datasources/PostgresDS" pool-name="PostgresDS" enabled="true"> <connection-url>jdbc:postgresql://localhost:5432/你的Django数据库名</connection-url> <driver>postgresql</driver> <security> <user-name>数据库用户名</user-name> <password>数据库密码</password> </security> </datasource> <drivers> <driver name="postgresql" module="org.postgresql"> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> </driver> </drivers>
Quarkus版本(Keycloak 17+)
修改keycloak.conf:
db=postgres db-url=jdbc:postgresql://localhost:5432/你的Django数据库名 db-username=数据库用户名 db-password=数据库密码
2. 配置JDBC用户存储提供商
登录Keycloak Admin控制台,进入目标Realm → User Federation → 选择JDBC:
- 选择刚才配置的
PostgresDS数据源 - 映射用户表字段:
- 用户表名:
auth_user - 用户名字段:
username - 密码字段:
password - 邮箱字段:
email - 启用状态字段:
is_active
- 用户表名:
- 映射角色关联:
- 角色表名:
auth_group - 角色名称字段:
name - 用户-角色关联表:
auth_user_groups - 用户ID外键:
user_id - 角色ID外键:
group_id
- 角色表名:
3. 匹配Django密码加密规则
Django默认用pbkdf2_sha256加密,需要在Keycloak中配置对应哈希算法:
- 进入Realm → Realm Settings → Password Policy → 添加Hash Algorithm
- 选择
pbkdf2-sha256,配置参数:- Iterations:和Django
settings.py中PASSWORD_HASHERS的迭代次数一致(默认180000) - Salt Size:32
- Key Size:256
Keycloak会自动解析Django的密码格式(如pbkdf2_sha256$180000$salt$hash)。
- Iterations:和Django
第二步:Spring Boot集成Keycloak认证
1. 添加依赖
在pom.xml中引入Spring Security和Keycloak Starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> <version>22.0.1</version> <!-- 与你的Keycloak版本保持一致 --> </dependency>
2. 配置application.properties
# Keycloak核心配置 keycloak.realm=你的Realm名称 keycloak.auth-server-url=http://localhost:8080/auth keycloak.resource=你的客户端ID keycloak.credentials.secret=你的客户端密钥 keycloak.use-resource-role-mappings=true keycloak.bearer-only=true # 跨域配置(按需添加) spring.web.cors.allowed-origins=* spring.web.cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS spring.web.cors.allowed-headers=*
3. 配置Spring Security规则
创建SecurityConfig类,保护API接口:
import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; 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.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; @KeycloakConfiguration public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider(); // 移除Keycloak默认的ROLE_前缀(如果Django角色名不带该前缀) provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(provider); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new NullAuthenticatedSessionStrategy(); // 无状态认证,适配API场景 } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.csrf().disable() .authorizeRequests() .antMatchers("/public/**").permitAll() // 公开接口无需认证 .antMatchers("/admin/**").hasRole("admin") // 需admin角色 .antMatchers("/user/**").hasRole("user") // 需user角色 .anyRequest().authenticated(); } }
4. 获取当前用户信息
在Controller中通过SecurityContext获取用户身份:
import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/user/me") public String getCurrentUser() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return "当前用户:" + auth.getName() + ",角色:" + auth.getAuthorities(); } }
第三步:测试验证
- 启动Keycloak,确认User Federation能加载Django中的用户和角色
- 启动Spring Boot应用
- 通过Keycloak获取Token:
curl -X POST http://localhost:8080/auth/realms/你的Realm名称/protocol/openid-connect/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=Django用户名" \ -d "password=Django用户密码" \ -d "grant_type=password" \ -d "client_id=你的客户端ID" \ -d "client_secret=你的客户端密钥" - 用
access_token访问受保护接口:curl -H "Authorization: Bearer 你的access_token" http://localhost:8080/user/me
注意事项
- 确保Keycloak与Spring Boot Starter版本兼容,避免依赖冲突
- 若Django用户表字段自定义,需在Keycloak的JDBC配置中调整字段映射
- 密码加密参数必须与Django完全一致,否则登录失败
- 如需实时同步Django的用户/角色变更,可在Keycloak的JDBC Provider中设置
Sync Period
内容的提问来源于stack exchange,提问作者Whiteox
相关产品推荐
相关产品推荐

