如何在WildFly Elytron Security中获取自定义Principal对象?
在WildFly 26 Elytron中获取自定义Principal对象
要让request.getUserPrincipal()返回自定义Principal,核心是在Elytron的认证流程中构建包含自定义Principal的SecurityIdentity,而非依赖默认的NamedPrincipal。以下是具体实现步骤:
1. 定义自定义Principal类
创建实现java.security.Principal的自定义类,建议实现序列化并重写必要方法以保证正确性:
import java.security.Principal; import java.io.Serializable; public class CustomPrincipal implements Principal, Serializable { private final String name; private final String userRole; // 自定义扩展属性 public CustomPrincipal(String name, String userRole) { this.name = name; this.userRole = userRole; } @Override public String getName() { return name; } public String getUserRole() { return userRole; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CustomPrincipal that = (CustomPrincipal) o; return name.equals(that.name) && userRole.equals(that.userRole); } @Override public int hashCode() { return name.hashCode() + userRole.hashCode(); } @Override public String toString() { return "CustomPrincipal{" + "name='" + name + '\'' + ", userRole='" + userRole + '\'' + '}'; } }
2. 实现自定义Elytron SecurityRealm
扩展Elytron的SecurityRealm接口,在认证逻辑中返回自定义Principal:
import org.wildfly.security.auth.server.RealmIdentity; import org.wildfly.security.auth.server.SecurityRealm; import org.wildfly.security.authz.AuthorizationIdentity; import org.wildfly.security.credential.Credential; import org.wildfly.security.credential.PasswordCredential; import org.wildfly.security.password.Password; import org.wildfly.security.password.interfaces.ClearPassword; public class CustomSecurityRealm implements SecurityRealm { @Override public RealmIdentity getRealmIdentity(String username) { // 模拟从数据源获取用户信息,实际应替换为数据库/LDAP查询逻辑 String storedPassword = "user123"; String userRole = "admin"; return new RealmIdentity() { @Override public AuthorizationIdentity getAuthorizationIdentity() { // 可根据需求配置角色授权信息,此处简化返回空实例 return AuthorizationIdentity.EMPTY; } @Override public boolean verifyCredential(Credential credential) { if (!(credential instanceof PasswordCredential)) return false; Password password = ((PasswordCredential) credential).getPassword(); if (!(password instanceof ClearPassword)) return false; String inputPassword = new String(((ClearPassword) password).getPassword()); return storedPassword.equals(inputPassword); } @Override public Principal getRealmPrincipal() { // 返回自定义Principal实例 return new CustomPrincipal(username, userRole); } @Override public boolean exists() { return true; } }; } // 其他未实现方法可抛出UnsupportedOperationException或返回默认值 }
3. 在WildFly中配置自定义安全域
- 将自定义Realm打包为JAR,放置到WildFly的
modules/system/layers/base/com/yourdomain/security/main目录,同时创建module.xml:
<?xml version="1.0" encoding="UTF-8"?> <module name="com.yourdomain.security" xmlns="urn:jboss:module:1.9"> <resources> <resource-root path="custom-security-realm.jar"/> </resources> <dependencies> <module name="org.wildfly.security.elytron"/> <module name="javax.api"/> </dependencies> </module>
- 通过WildFly CLI执行配置命令:
# 添加自定义安全Realm /subsystem=elytron/custom-security-realm=customRealm:add(class-name=com.yourdomain.security.CustomSecurityRealm, module=com.yourdomain.security) # 创建安全域并关联Realm /subsystem=elytron/security-domain=customDomain:add(realms=[{realm=customRealm, role-decoder=groups-to-roles}], default-realm=customRealm, permission-mapper=default-permission-mapper) # 将安全域关联到Undertow /subsystem=undertow/application-security-domain=customDomain:add(security-domain=customDomain)
4. 应用中配置使用安全域
在web应用的web.xml中配置安全约束:
<security-constraint> <web-resource-collection> <web-resource-name>Protected Resources</web-resource-name> <url-pattern>/secured/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>customDomain</realm-name> </login-config> <security-role> <role-name>admin</role-name> </security-role>
在jboss-web.xml中指定安全域:
<?xml version="1.0" encoding="UTF-8"?> <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_10_0.xsd" version="10.0"> <context-root>/your-app</context-root> <security-domain>customDomain</security-domain> </jboss-web>
5. 代码中获取自定义Principal
在Servlet或业务代码中直接强转获取:
CustomPrincipal customPrincipal = (CustomPrincipal) request.getUserPrincipal(); String userRole = customPrincipal.getUserRole(); // 基于自定义属性实现业务逻辑
关键注意事项
- 避免混用传统JAAS登录模块与Elytron,Elytron的认证模型独立于JAAS,混用会导致默认
NamedPrincipal被返回。 - 确保自定义Principal类在WildFly模块和应用中均可访问(可打包到应用或配置正确的模块依赖)。
- 自定义Realm的
getRealmPrincipal()方法必须返回自定义Principal实例,这是核心步骤。
内容的提问来源于stack exchange,提问作者Mono
相关产品推荐
相关产品推荐

