[英]Wildfly and JAAS login module
I'm playing with Wildfly-9.0.1.Final
and JAAS
but I'm not having so much fun.. I implemented my custom login module: 我正在玩
Wildfly-9.0.1.Final
和JAAS
但是我玩的不多。.我实现了自定义登录模块:
public class MongoLoginModule implements LoginModule {
@Inject
protected MongoDB mongoDb;
protected Subject subject;
protected Principal identity;
protected boolean loginOk;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
private Logger log = LoggerFactory.getLogger(MongoLoginModule.class);
public boolean abort() throws LoginException {
log.info("abort!");
subject = null;
return true;
}
public boolean commit() throws LoginException {
// TODO Auto-generated method stub
log.info("commit!");
if(loginOk) {
UserGroup userGroup = new UserGroup("Roles");
userGroup.addMember(new RolePrincipal("userA"));
subject.getPrincipals().add(userGroup);
subject.getPublicCredentials().add(userGroup);
return true;
}
return false;
}
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
log.info("Initializing MongoLoginModule.");
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
}
public boolean login() throws LoginException {
log.info("login requested.");
NameCallback nameCallback = new NameCallback("username:");
PasswordCallback passwordCallback = new PasswordCallback("password:", false);
try {
callbackHandler.handle(new Callback[]{nameCallback, passwordCallback});
String username = nameCallback.getName();
String password = new String(passwordCallback.getPassword());
log.info("check credentials for: "+username);
if(username.equals("jim") && password.equals("jim")) {
loginOk = true;
identity = new UserPrincipal(username);
subject.getPrincipals().add(identity);
subject.getPublicCredentials().add(identity);
return true;
}
} catch (IOException e) {
e.printStackTrace();
} catch (UnsupportedCallbackException e) {
e.printStackTrace();
}
return false;
}
public boolean logout() throws LoginException {
if(subject != null && identity != null) {
subject.getPrincipals().remove(identity);
return true;
}
return false;
}
public Document getUserByName(String userName) {
FindIterable<Document> results = mongoDb.getCollection().find(new Document("username", userName));
return results.iterator().next();
}
public void getRoles() {
// FindIterable<Document> results = mongoDb.getCollection().find(new Document("username", userName));
// results.iterator().next().get
}
It's not perfect but it's enought for now. 这不是完美的,但现在已经足够了。 This pure JAAS login module is a module in my Wildfly.
这个纯JAAS登录模块是Wildfly中的一个模块。 I configure the security domain this way:
我以这种方式配置安全域:
<security-domain name="MongoLoginRealm" cache-type="default">
<authentication>
<login-module code="it.bytebear.jaas.mongo.module.MongoLoginModule" flag="required" module="login.mongodb">
<module-option name="mongodb.uri" value="mongodb://localhost:21017/test?collection"/>
</login-module>
</authentication>
</security-domain>
I implemented some RESTful web service to do some test. 我实现了一些RESTful Web服务来进行一些测试。 I'm only posting the relevant code:
我只发布相关代码:
...
@POST
@Path("/login")
@PermitAll
@Consumes(MediaType.APPLICATION_JSON)
// @Consumes("application/x-authc-username-password+json")
public Response login(User userCredentials) {
log.info("logging in.");
try {
MongoModuleCallbackHandler handler = new MongoModuleCallbackHandler();
handler.setUsername(userCredentials.getUserName());
handler.setPassword(userCredentials.getPassword().toCharArray());
LoginContext loginContext = new LoginContext("MongoLoginRealm", handler);
loginContext.login();
Subject subject = loginContext.getSubject();
List<String> roles = new ArrayList<String>();
for (Principal p : subject.getPrincipals()) {
roles.add(p.getName());
}
userCredentials.setRoles((String[]) roles.toArray());
return Response.ok().entity(userCredentials)
.type(MediaType.APPLICATION_JSON_TYPE).build();
} catch (Exception e) {
log.error("login fails.", e);
return Response.status(Status.FORBIDDEN).entity("Not logged")
.type(MediaType.APPLICATION_JSON_TYPE).build();
}
}
...
In web.xml
auth-method
is BASIC
and realm-name
is MongoLoginRealm
, the same used in jboss-web.xml
and when instantiating LoginContext
. 在
web.xml
auth-method
是BASIC
, realm-name
是MongoLoginRealm
,与jboss-web.xml
和实例化LoginContext
时使用的相同。 When I invoke the login
method I got this exception: 当我调用
login
方法时,出现以下异常:
22:39:49,421 ERROR [it.bytebear.web.mongo.UserServices] (default task-1) login fails.: javax.security.auth.login.LoginException: impossibile trovare la classe Login
Module: it.bytebear.jaas.mongo.module.MongoLoginModule from [Module "deployment.MongoWebTest.war:main" from Service Module Loader]
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:822)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695)
at javax.security.auth.login.LoginContext.login(LoginContext.java:594)
at it.bytebear.web.mongo.UserServices.login(UserServices.java:66)
My login module is never been executed. 我的登录模块从未执行过。 What am I missing?
我想念什么?
UPDATE: Moving the login module .jar into the web application it works. 更新:将登录模块.jar移到它可以工作的Web应用程序中。 Maybe there is something wrong in my Wildfly.
也许我的Wildfly中出了点问题。 Here is my module structure:
这是我的模块结构:
%wildfly_home%/modules/system/layers/base/login/mongodb/main/module.xml
%wildfly_home%/modules/system/layers/base/login/mongodb/main/mongo-java-driver-3.0.3.jar
%wildfly_home%/modules/system/layers/base/login/mongodb/main/MongoLoginModule.jar
and this is the module.xml
: 这是
module.xml
:
<module xmlns="urn:jboss:module:1.1" name="login.mongodb">
<resources>
<resource-root path="MongoLoginModule.jar"/>
<resource-root path="mongo-java-driver-3.0.3.jar"/>
</resources>
<dependencies>
<module name="org.apache.log4j"/>
<module name="javax.api"/>
<module name="org.slf4j"/>
</dependencies>
</module>
I have to figure out why the login module isn't reachable as Wildfly module. 我必须弄清楚为什么登录模块无法作为Wildfly模块访问。
It's probably an issue (or feature) of the WildFly. 这可能是WildFly的问题(或功能)。 I've reported it as WildFly JIRA WFLY-5569 .
我将其报告为WildFly JIRA WFLY-5569 。
You can still use standard servlet authentication which works correctly. 您仍然可以使用正常工作的标准servlet身份验证。
Add WEB-INF/jboss-web.xml
file to your deployment: 将
WEB-INF/jboss-web.xml
文件添加到您的部署中:
<jboss-web>
<security-domain>MongoLoginRealm</security-domain>
</jboss-web>
Adjust your code to use HttpServletRequest.login(String, String)
method 调整您的代码以使用
HttpServletRequest.login(String, String)
方法
@Context
private HttpServletRequest req;
@POST
@Path("/login")
@PermitAll
@Consumes(MediaType.APPLICATION_JSON)
public Response login(User userCredentials) {
try {
req.login(userCredentials.getUserName(),
userCredentials.getPassword());
Subject subject = org.jboss.security.SecurityContextAssociation.getSubject();
Optional<Group> rolesGroup = subject.getPrincipals(Group.class).stream().filter(p -> "Roles".equals(p.getName()))
.findFirst();
if (rolesGroup.isPresent()) {
List<String> roleNames = Collections.list(rolesGroup.get().members()).stream().map(p -> p.getName())
.collect(Collectors.toList());
// ...
} else {
// ...
}
} catch (ServletException e) {
log.error("login fails.", e);
return Response.status(Status.FORBIDDEN).entity("Not logged")
.type(MediaType.APPLICATION_JSON_TYPE).build();
}
}
My application can't find the module because I forgot to add Dependency
to it's MANIFEST
or to declare login.mongodb
as a global module in Wildfly. 我的应用程序找不到该模块,因为我忘记将
Dependency
添加到它的MANIFEST
或将login.mongodb
声明为login.mongodb
中的全局模块。 Thanks @kwart for your suggestion and your answer, you point me to the right direction. 感谢@kwart的建议和回答,您为我指明了正确的方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.