我们的项目由一个 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 - Jaas JDBC 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37058556/