java - Jaas JDBC 身份验证

标签 java authentication jdbc jaas

我们的项目由一个 JavaFX 应用程序组成,它通过 RMI 协议(protocol)调用 JEE 服务器。 我们使用 Payara 应用服务器,一个 Glassfish 分支。 我们希望将 JAAS 与数据库结合使用来管理授予用户的身份验证和权限。

我们不知道如何将创建的 JDBC 领域与我们的应用程序绑定(bind)以与数据库交互。

我们能否以编程方式调用领域或直接查询数据库 here

启动 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;
    }
}

登录模块:

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;
    }
}

回调处理程序:

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");
            }
        }
    }
}

我们在应用服务器上创建了一个 JDBC 领域: JDBC Realm Image

最佳答案

如果您期望通过调用 AuthenticationService#login 您将登录(通过身份验证)Java EE 服务器 (Payara),那么这绝对是错误的方法。

调用lc.login();后,Java EE 服务器不会以任何方式意识到该调用。使用 new 运算符实例化的随机 LoginContext 不会神奇地连接到 Java EE 环境。

如果您正在进行远程 EJB 调用,则需要为该调用提供身份验证数据(来自 JavaFx 应用程序),然后以 GlassFish/Payara 特定方式为(远程)EJB 配置身份验证。与 Servlet 相反,Java EE 中没有标准方法来对 EJB 进行身份验证(对于 Servlet,您将使用 JASPIC)。

也没有标准的LoginModule之类的东西。 GlassFish 确实使用了 LoginModule 接口(interface),但是以一种高度 GlassFish 特定的方式。如果您只想使用 JDBC 领域(领域是此处“身份存储”的另一个术语,也是“登录模块”的另一个术语),您“仅”需要使用 glassfish 特定的 glassfish-ejb 进行配置jar.xml 文件。不幸的是,几乎没有人知道如何准确地做到这一点,但我认为您需要研究 ior-security-config 并从那里进行研究。

或者,您也可以使用 ProgrammaticLogin 类,它是 GlassFish 特定的 EJB,相当于标准 HttpServletRequest#login

参见Java EE 6 Application Client login

关于java - Jaas JDBC 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37058556/

相关文章:

c# - 如何在 MVC 5 中设置自定义 ClaimsPrincipal?

java - 如何通过JDBC提供数据库独立性?

java - 需要 HTML 页面作为从一个应用程序到另一应用程序的响应

java - JComboBox TableCellRenderer 似乎失去了它的值(value),尽管该值被保存了

Java:为什么迭代器不可复制

java - java中异常处理和finally阻塞的疑惑

Azure 中的 Tomcat 负载平衡

windows - Windows XP 和 Unix 中的 kerberos 票证 TGT 和服务票证的路径?

java - 在JAVA中读取JSON数组

java - SQLException 从 JTable 和数据库中删除行