简体   繁体   English

Jaas JDBC 认证

[英]Jaas JDBC Authentication

Our project consists of a JavaFX app who calls the JEE server by RMI protocol.我们的项目由一个 JavaFX 应用程序组成,它通过 RMI 协议调用 JEE 服务器。 We use the Payara app server, a Glassfish fork.我们使用 Payara 应用服务器,一个 Glassfish 分支。 We want to use JAAS with a database to manage authentication and permissions granted to a user.我们希望将 JAAS 与数据库一起使用来管理授予用户的身份验证和权限。

We do not understand how to bind the created JDBC realm with our application to interact with a database.我们不明白如何将创建的 JDBC 领域与我们的应用程序绑定以与数据库交互。

Can we programmatically call the realm or directly query the database as here ?我们可以通过编程调用领域或直接查询数据库, 在这里

The service starting the LoginContext :启动 LoginContext 的服务:

@Stateless
public class AuthenticationService implements IAuthenticationService {
    @Override
    public boolean login(User user) {
        try {
            LoginContext lc = new LoginContext(
                "JDBCLoginModule",
                new JDBCCallbackHandler(user.getUsername(), user.getPassword())
            );

            lc.login();

            Subject subject = lc.getSubject();

            return true;

        } catch (LoginException ex) {
            ex.printStacktrace();
        }
        return false;
    }
}

The LoginModule :登录模块:

public class JDBCLoginModule implements LoginModule {
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map options;

    private boolean succeeded = false;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        this.subject            = subject;
        this.callbackHandler    = callbackHandler;
        this.sharedState        = sharedState;
        this.options            = options;
        succeeded               = false;
    }

    @Override
    public boolean login() throws LoginException {
        if (callbackHandler == null)
            throw new LoginException("The callbackHandler is null");

        Callback[] callbacks = new Callback[2];
        callbacks[0] = new NameCallback("name:");
        callbacks[1] = new PasswordCallback("password:", false);

        try {
            callbackHandler.handle(callbacks);
        } catch (IOException e) {
            throw new LoginException("IOException calling handle on callbackHandler");
        }
        catch (UnsupportedCallbackException e) {
            throw new LoginException("UnsupportedCallbackException calling handle on callbackHandler");
        }

        NameCallback nameCallback           = (NameCallback) callbacks[0];
        PasswordCallback passwordCallback   = (PasswordCallback) callbacks[1];

        String name = nameCallback.getName();
        String password = new String(passwordCallback.getPassword());

        // Call the JDBC Realm
        /*if ("myName".equals(name) && "myPassword".equals(password)) {
            succeeded = true;
            return succeeded;
        }
        else {
            succeeded = false;
            throw new FailedLoginException("Sorry! No login for you.");
        }*/
    }

    @Override
    public boolean commit() throws LoginException {
        return succeeded;
    }

    @Override
    public boolean abort() throws LoginException {
        return false;
    }

    @Override
    public boolean logout() throws LoginException {
        return false;
    }
}

The CallBackHandler :回调处理程序:

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

    public JDBCCallbackHandler(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
            if (callbacks[i] instanceof NameCallback) {
                NameCallback nameCallback = (NameCallback) callbacks[i];
                nameCallback.setName(username);
            }
            else if (callbacks[i] instanceof PasswordCallback) {
                PasswordCallback passwordCallback = (PasswordCallback) callbacks[i];
                passwordCallback.setPassword(password.toCharArray());
            }
            else {
                throw new UnsupportedCallbackException(callbacks[i], "The submitted Callback is unsupported");
            }
        }
    }
}

We created a JDBC realm on the app server: JDBC Realm Image我们在应用服务器上创建了一个 JDBC 领域: JDBC Realm Image

If you expected that by calling AuthenticationService#login you'll be logged-in (authenticated) for the Java EE server (Payara), then this is absolutely the wrong approach.如果您期望通过调用AuthenticationService#login您将登录(验证)Java EE 服务器(Payara),那么这绝对是错误的方法。

After the call to lc.login();在调用lc.login(); the Java EE server is not in any way aware of that call. Java EE 服务器丝毫不知道该调用。 A random LoginContext that you instantiate with the new operator does not magically become connected to the Java EE environment.使用 new 运算符实例化的随机LoginContext不会神奇地连接到 Java EE 环境。

If you're making a remote EJB call, you need to provide the authentication data with that call (from the JavaFx application) and then configure authentication for (remote) EJB in a GlassFish/Payara specific way.如果您进行远程 EJB 调用,则需要通过该调用(来自 JavaFx 应用程序)提供身份验证数据,然后以 GlassFish/Payara 特定方式为(远程)EJB 配置身份验证。 Contrary to Servlets, there is no standard way in Java EE to authenticate for EJB (for Servlets you'd be using JASPIC for this).与 Servlet 不同,Java EE 中没有标准的方法来验证 EJB(对于 Servlet,您将为此使用 JASPIC)。

There's also no such thing as a standard LoginModule .也没有标准LoginModule这样的东西。 GlassFish does uses the LoginModule interface, but in a highly GlassFish specific way. GlassFish 确实使用了LoginModule接口,但是以一种高度特定于 GlassFish 的方式。 If you only want to use the JDBC realm (realm is another term for "identity store" here, which is another term for "login module") you 'only' need to configure this using the glassfish specific glassfish-ejb-jar.xml file.如果您只想使用 JDBC 领域(领域是此处“身份存储”的另一个术语,它是“登录模块”的另一个术语),您“仅”需要使用 glassfish 特定的glassfish-ejb-jar.xml对其进行配置文件。 Unfortunately, almost nobody knows how to do this exactly, but I think you need to look into the ior-security-config and research from there.不幸的是,几乎没有人知道如何准确地做到这一点,但我认为您需要查看ior-security-config并从那里进行研究。

Alternatively, you may be able to use the ProgrammaticLogin class, which is the GlassFish specific EJB equivalent to the standard HttpServletRequest#login .或者,您可以使用ProgrammaticLogin类,它是 GlassFish 特定的 EJB,相当于标准HttpServletRequest#login

See Java EE 6 Application Client login请参阅Java EE 6 应用程序客户端登录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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