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

如何在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中配置自定义安全域

  1. 将自定义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>
  1. 通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:10:40