Wildfly 8 Wildfly 8自定义登录模块访问HttpServletRequest参数

Wildfly 8 Wildfly 8自定义登录模块访问HttpServletRequest参数,wildfly-8,Wildfly 8,我正在调查使用wildfly自定义登录模块的可行性 客户端将移动设备id作为登录的一部分传递给服务器。我将以通常的方式检查用户名和密码是否正确,然后我需要检查移动设备是否获准使用该服务 这个想法是我将有一个RESTfulWebService方法login,它调用HttpServletRequest.login(u,p) 如何在HttpServletRequest的登录模块中获取移动设备id 我可以登录,如果登录成功,然后在webservice中测试设备id,如果未获得批准,则注销用户。但这似乎相

我正在调查使用wildfly自定义登录模块的可行性

客户端将移动设备id作为登录的一部分传递给服务器。我将以通常的方式检查用户名和密码是否正确,然后我需要检查移动设备是否获准使用该服务

这个想法是我将有一个RESTfulWebService方法login,它调用HttpServletRequest.login(u,p)

如何在HttpServletRequest的登录模块中获取移动设备id

我可以登录,如果登录成功,然后在webservice中测试设备id,如果未获得批准,则注销用户。但这似乎相当混乱

正确的做法是什么

编辑

反馈:我按照克里斯的建议做了。我实现了自己版本的CallBackHandler和回调接口的实现,在登录模块的登录方法中,我执行以下操作:

public boolean login() throws LoginException {

        boolean login = super.login();

        if (login) {

            UuidCallback uuidCallback = new UuidCallback();

            try {

                super.callbackHandler.handle(new Callback[]{uuidCallback});

            } catch (Exception e) {

                LoginException le = new LoginException("Failed to get uuid");
                le.initCause(e);

                throw le;
            }

            System.out.print("Device UUID: "+uuidCallback.getUuid());
    }

    return login;
}
在web服务登录方法中:

@Path("/login")
@Produces({ "application/json" })
public class LoginWebService {

    @POST
    public Response login(@Context HttpServletRequest request) throws LoginException {

        CallbackHandler callbackHandler = new MyCallbackHandler(request.getParameter("username"), request.getParameter("password"), request.getParameter("uuid"));

        Subject subject = new Subject();
        LoginContext loginContext = new LoginContext("securityDomain", new subject, callbackHandler);

        loginContext.login();

        MyPrincipal principal = subject.getPrincipals(MyPrincipal.class).iterator().next();
    }
}
您还可以在回调处理程序上设置uuid,然后在
LoginModule.login
方法中调用回调处理程序上的
getUUID()
。但是我选择了这个设计,尽管它对我来说不太合理

当我登录并尝试访问受保护的资源时,我仍然得到403。结果表明,如果
auth constraint/role name
为*,则必须至少提供一个
安全角色

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>mydomain</realm-name>
</login-config>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>rest</web-resource-name>
        <url-pattern>/rest/app/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>
</security-constraint>
<!-- after login there is a 403 on protected resources if no role and role-name * -->
<security-role>
    <role-name>user</role-name>
</security-role>

形式
mydomain
休息
/休息/应用/*
*
用户
我的所有用户都有一个角色user,该角色授予他们访问权限。我可以通过排除
安全角色
使其正常工作,但是
auth constraint/role name
必须设置为文字角色,在我的例子中:“user”

而不是直接从restful Web服务调用HttpServletRequest.login()方法,您可以在Wildfly中配置安全域

此安全域应在您的webapp web.xml文件login config元素中引用,并带有安全约束,以启用

下面是一个声明安全约束和登录配置(使用基本身份验证方法)的示例

以及用于安全域配置的Wildfly standalone.xml配置示例,使用标准提供的数据库登录模块,而不是自定义模块:

<security-domain name="securityDomain" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:/TestDS"/>
            <module-option name="principalsQuery" value="select password from User where login = ? and (disabled is null or disabled = 0) and activated = 1"/>
            <module-option name="rolesQuery" value="select name,'Roles' from Role r, User_Role ur, User u where u.login=? and u.id = ur.userId and r.id = ur.roleId"/>
            <module-option name="hashAlgorithm" value="SHA-256"/>
            <module-option name="hashEncoding" value="base64"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>
    </authentication>
</security-domain>

然后,在REST资源中,您只需使用@RolesAllowed或@PermitAll注释来限制访问或不进行授权。

您可以在Wildfly中配置安全域,而不是直接从restful Web服务调用HttpServletRequest.login()方法

此安全域应在您的webapp web.xml文件login config元素中引用,并带有安全约束,以启用

下面是一个声明安全约束和登录配置(使用基本身份验证方法)的示例

以及用于安全域配置的Wildfly standalone.xml配置示例,使用标准提供的数据库登录模块,而不是自定义模块:

<security-domain name="securityDomain" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:/TestDS"/>
            <module-option name="principalsQuery" value="select password from User where login = ? and (disabled is null or disabled = 0) and activated = 1"/>
            <module-option name="rolesQuery" value="select name,'Roles' from Role r, User_Role ur, User u where u.login=? and u.id = ur.userId and r.id = ur.roleId"/>
            <module-option name="hashAlgorithm" value="SHA-256"/>
            <module-option name="hashEncoding" value="base64"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>
    </authentication>
</security-domain>


然后,在您的REST资源中,您只需使用@RolesAllowed或@PermitAll注释来限制访问或不进行授权。

我建议创建LoginContext并传递回调处理程序的实现。在callbackhandler中,提供额外的UUID属性

虽然这段代码对我有效,但您需要对其进行更新以满足额外的UUID属性

public class NamePasswordCallbackHandler implements CallbackHandler {
    private final String username;
    private final String password;

    private NamePasswordCallbackHandler(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback current : callbacks) {
            if (current instanceof NameCallback) {
                ((NameCallback) current).setName(username);
            } else if (current instanceof PasswordCallback) {
                ((PasswordCallback) current).setPassword(password.toCharArray());
            } else {
                throw new UnsupportedCallbackException(current);
            }
        }
    }
}
我创建了自己的配置对象实现(如下所示为JBossJaasConfiguration)

然后将此回调处理程序传递给您的LoginContext:

CallbackHandler cbh = new NamePasswordCallbackHandler(username, password);
Configuration config = new JBossJaasConfiguration("mysqldomain");

LoginContext loginContext = new LoginContext("mycontext", new Subject(), cbh, config);
loginContext.login();
属性“mysqldomain”与standalone.xml中的安全域名相关

<subsystem xmlns="urn:jboss:domain:security:1.2">
    <security-domains>
        <security-domain name="mysqldomain" cache-type="default">
             <authentication>
                  <login-module code="com.soccerx.security.DatabaseServerLoginRealm" flag="required">
                     <module-option name="dsJndiName" value="java:jboss/datasources/SoccerSoftwareDS"/>
                     <module-option name="principalsQuery" value="select userId, tenantId, password, salt from User where username=? and StatusId != 2"/>

            <module-option name="rolesQuery" value="select Role, 'Roles' from User where Username=?"/>
                    <module-option name="password-stacking" value="useFirstPass"/>
                    <module-option name="principalClass" value="com.soccerx.security.DatabasePrincipal"/>
                </login-module>
            </authentication>
        </security-domain>
    <security-domains>
</subsystem>


我建议创建一个LoginContext并传递CallbackHandler的实现。在callbackhandler中,提供额外的UUID属性

虽然这段代码对我有效,但您需要对其进行更新以满足额外的UUID属性

public class NamePasswordCallbackHandler implements CallbackHandler {
    private final String username;
    private final String password;

    private NamePasswordCallbackHandler(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback current : callbacks) {
            if (current instanceof NameCallback) {
                ((NameCallback) current).setName(username);
            } else if (current instanceof PasswordCallback) {
                ((PasswordCallback) current).setPassword(password.toCharArray());
            } else {
                throw new UnsupportedCallbackException(current);
            }
        }
    }
}
我创建了自己的配置对象实现(如下所示为JBossJaasConfiguration)

然后将此回调处理程序传递给您的LoginContext:

CallbackHandler cbh = new NamePasswordCallbackHandler(username, password);
Configuration config = new JBossJaasConfiguration("mysqldomain");

LoginContext loginContext = new LoginContext("mycontext", new Subject(), cbh, config);
loginContext.login();
属性“mysqldomain”与standalone.xml中的安全域名相关

<subsystem xmlns="urn:jboss:domain:security:1.2">
    <security-domains>
        <security-domain name="mysqldomain" cache-type="default">
             <authentication>
                  <login-module code="com.soccerx.security.DatabaseServerLoginRealm" flag="required">
                     <module-option name="dsJndiName" value="java:jboss/datasources/SoccerSoftwareDS"/>
                     <module-option name="principalsQuery" value="select userId, tenantId, password, salt from User where username=? and StatusId != 2"/>

            <module-option name="rolesQuery" value="select Role, 'Roles' from User where Username=?"/>
                    <module-option name="password-stacking" value="useFirstPass"/>
                    <module-option name="principalClass" value="com.soccerx.security.DatabasePrincipal"/>
                </login-module>
            </authentication>
        </security-domain>
    <security-domains>
</subsystem>


要确认,我是否将创建LoginContext并从我的webservice登录方法中调用login?是的,完全正确。还要创建MobileIdCallback对象。要确认,我是否将创建LoginContext并从我的webservice登录方法内部调用login?是的,完全正确。还要创建MobileIdCallback对象。