You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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:和Djangosettings.py中PASSWORD_HASHERS的迭代次数一致(默认180000)
    • Salt Size:32
    • Key Size:256
      Keycloak会自动解析Django的密码格式(如pbkdf2_sha256$180000$salt$hash)。

第二步: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();
    }
}

第三步:测试验证

  1. 启动Keycloak,确认User Federation能加载Django中的用户和角色
  2. 启动Spring Boot应用
  3. 通过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=你的客户端密钥"
    
  4. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:39:54