基于Pac4j+Keycloak登录后获取用户信息及Shiro配置问题
基于Pac4j+Keycloak+Shiro的登录后用户信息处理方案
1. 核心实现逻辑
需要通过自定义Shiro Realm扩展Pac4jRealm,在认证流程中直接从Keycloak返回的用户Profile中提取信息,同时完成用户映射、会话存储、日志记录、权限配置等业务逻辑。必须修改shiro.ini,替换默认的Pac4jRealm为自定义实现类。
2. 自定义Keycloak Realm类
继承Pac4jRealm,重写认证方法,在基础认证完成后提取Keycloak用户信息并执行业务逻辑:
import org.pac4j.core.profile.CommonProfile; import org.pac4j.shiro.realm.Pac4jRealm; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.pac4j.core.profile.UserProfile; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.SecurityUtils; import java.util.List; import java.util.Set; public class CustomKeycloakRealm extends Pac4jRealm { // 注入数据库操作类(根据项目实际依赖方式调整) private UserMapper userMapper; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { // 完成Pac4j与Keycloak的基础认证流程 AuthenticationInfo authInfo = super.doGetAuthenticationInfo(token); // 获取Keycloak返回的用户Profile集合 List<UserProfile> profiles = getProfiles(token); if (profiles.isEmpty()) { return authInfo; } // 转换为通用Profile,提取邮箱(KeycloakProfile继承自CommonProfile) CommonProfile keycloakProfile = (CommonProfile) profiles.get(0); String userEmail = keycloakProfile.getEmail(); // 数据库查询:通过邮箱映射应用内用户 AppUser appUser = userMapper.findUserByEmail(userEmail); // 1. 存储用户信息到Shiro会话 SecurityUtils.getSubject().getSession().setAttribute("currentAppUser", appUser); // 2. 记录登录日志 UserLog.recordLogin(appUser.getUserId(), userEmail); // 3. 设置用户语言到会话 SecurityUtils.getSubject().getSession().setAttribute("userLocale", appUser.getLanguage()); // 4. 配置Shiro权限:添加应用内权限集 Set<String> userPermissions = appUser.getPermissions(); SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo(); authzInfo.setStringPermissions(userPermissions); ((SimpleAuthenticationInfo) authInfo).setAuthorizationInfo(authzInfo); return authInfo; } // 注入数据库Mapper的Setter方法(非Spring环境需手动初始化) public void setUserMapper(UserMapper userMapper) { this.userMapper = userMapper; } }
3. 修改shiro.ini配置
替换默认Realm为自定义实现,并配置Pac4j过滤器:
# 自定义Realm配置 customKeycloakRealm = com.yourcompany.app.shiro.CustomKeycloakRealm # 注入数据库操作类 customKeycloakRealm.userMapper = com.yourcompany.app.mapper.UserMapper # 绑定Realm到SecurityManager securityManager.realms = $customKeycloakRealm # Pac4j过滤器配置,关联已配置好KeycloakClient的Pac4j Config pac4jFilter = org.pac4j.shiro.filter.Pac4jFilter pac4jFilter.configFactory = com.yourcompany.app.config.KeycloakConfigFactory # 过滤链规则:指定需要认证的路径 [urls] /auth/login = pac4jFilter /** = authc
4. 关键注意事项
- 确保Keycloak客户端已配置返回
email属性:在Keycloak控制台的客户端「客户端范围」中,开启email属性的映射并添加到访问令牌 - 若项目基于Spring,可通过
@Component注解让Spring管理CustomKeycloakRealm,无需在shiro.ini中手动注入依赖 - AppUser类需实现
Serializable接口,才能正常存入Shiro会话 - 若不需要在Realm中处理所有业务,也可单独实现Pac4j的
AuthenticationSuccessHandler,但通过Realm集成更贴合Shiro的认证授权流程
内容的提问来源于stack exchange,提问作者vished2000
相关产品推荐
相关产品推荐

