简体   繁体   English

Wildfly和JAAS登录模块

[英]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.FinalJAAS但是我玩的不多。.我实现了自定义登录模块:

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-methodBASICrealm-nameMongoLoginRealm ,与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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM