Wildfly 8 Wildfly 8自定义登录模块访问HttpServletRequest参数
我正在调查使用wildfly自定义登录模块的可行性 客户端将移动设备id作为登录的一部分传递给服务器。我将以通常的方式检查用户名和密码是否正确,然后我需要检查移动设备是否获准使用该服务 这个想法是我将有一个RESTfulWebService方法login,它调用HttpServletRequest.login(u,p) 如何在HttpServletRequest的登录模块中获取移动设备id 我可以登录,如果登录成功,然后在webservice中测试设备id,如果未获得批准,则注销用户。但这似乎相当混乱 正确的做法是什么 编辑 反馈:我按照克里斯的建议做了。我实现了自己版本的CallBackHandler和回调接口的实现,在登录模块的登录方法中,我执行以下操作:Wildfly 8 Wildfly 8自定义登录模块访问HttpServletRequest参数,wildfly-8,Wildfly 8,我正在调查使用wildfly自定义登录模块的可行性 客户端将移动设备id作为登录的一部分传递给服务器。我将以通常的方式检查用户名和密码是否正确,然后我需要检查移动设备是否获准使用该服务 这个想法是我将有一个RESTfulWebService方法login,它调用HttpServletRequest.login(u,p) 如何在HttpServletRequest的登录模块中获取移动设备id 我可以登录,如果登录成功,然后在webservice中测试设备id,如果未获得批准,则注销用户。但这似乎相
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对象。