Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从jaas LoginModule访问spring上下文_Java_Spring_Spring Security_Jaas - Fatal编程技术网

Java 从jaas LoginModule访问spring上下文

Java 从jaas LoginModule访问spring上下文,java,spring,spring-security,jaas,Java,Spring,Spring Security,Jaas,为了执行身份验证,我实现了一个Jaas登录模块。我必须访问数据库以检索此模块中的用户/传递信息 在同一个项目中,存在一些实现的DAOBean,但是不可能从jaas登录模块访问Spring上下文来检索DAOBean 有人能帮我吗 我正在使用Spring Security将Jaas集成到我的应用程序中。如果您有权访问LoginModule,只需为LoginModule添加接口ApplicationContextAware和bean定义即可。当应用程序启动时,上下文将在模块内可用。 公共类LoginM

为了执行身份验证,我实现了一个Jaas登录模块。我必须访问数据库以检索此模块中的用户/传递信息

在同一个项目中,存在一些实现的DAOBean,但是不可能从jaas登录模块访问Spring上下文来检索DAOBean

有人能帮我吗


我正在使用Spring Security将Jaas集成到我的应用程序中。

如果您有权访问LoginModule,只需为LoginModule添加接口ApplicationContextAware和bean定义即可。当应用程序启动时,上下文将在模块内可用。
公共类LoginModule实现ApplicationContextAware{
私有应用程序上下文应用程序上下文;
public void setApplicationContext(ApplicationContext ApplicationContext)抛出BeansException{
this.applicationContext=applicationContext;
} 
}

接口的Javadoc:

JAAS和登录模块在主Spring框架上下文旁加载和初始化。这是java平台完成的工作,它不知道您打算使用Spring。 因此,您需要通过某种单例或持有者将Spring上下文连接到登录模块。更优雅的方法是实现您自己的
AuthenticationProvider
,它是合法的Springbean

为了解决这个问题,以及其他对在没有显式访问的情况下获取Spring应用程序上下文感兴趣的人,我想提供一个示例。 请记住,虽然这种方法是可移植的,但由于类加载器可见性导致多个单例,您可能会遇到各种问题。在任何应用程序服务器或servlet容器中运行此代码时都要小心

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Optional;

public class SpringContextHolder implements ApplicationContextAware, InitializingBean {

    private static SpringContextHolder INSTANCE;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public Optional<ApplicationContext> getApplicationContext() {
        return Optional.ofNullable(applicationContext);
    }

    public static Optional<SpringContextHolder> getInstance() {
        return Optional.ofNullable(INSTANCE);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        INSTANCE = this;
    }
}
import org.springframework.beans.BeansException;
导入org.springframework.beans.factory.initializebean;
导入org.springframework.context.ApplicationContext;
导入org.springframework.context.ApplicationContextAware;
导入java.util.Optional;
公共类SpringContextHolder实现ApplicationContextAware,初始化Bean{
私有静态SpringContextHolder实例;
私有应用程序上下文应用程序上下文;
@凌驾
public void setApplicationContext(ApplicationContext ApplicationContext)抛出BeansException{
this.applicationContext=applicationContext;
}
公共可选getApplicationContext(){
返回可选的.ofNullable(applicationContext);
}
公共静态可选getInstance(){
返回可选的.ofNullable(实例);
}
@凌驾
public void afterPropertieSet()引发异常{
实例=此;
}
}
然后,您的登录模块可以通过singleton访问应用程序上下文:

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.spi.LoginModule;
import java.util.Map;

public class TokenLoginModule implements LoginModule {

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        ApplicationContext context = SpringContextHolder.getInstance()
            .flatMap(SpringContextHolder::getApplicationContext)
            .orElseThrow(() -> new RuntimeException("Unable to locate Spring context"));

       // lookup via context.getBean or just store it as a field
    }
}
import org.springframework.context.ApplicationContext;
导入org.springframework.context.ApplicationContextAware;
导入javax.security.auth.Subject;
导入javax.security.auth.callback.CallbackHandler;
导入javax.security.auth.spi.LoginModule;
导入java.util.Map;
公共类TokenLoginModule实现LoginModule{
@凌驾
public void initialize(主题主题、CallbackHandler CallbackHandler、映射共享状态、映射选项){
ApplicationContext上下文=SpringContextHolder.getInstance()
.flatMap(SpringContextHolder::getApplicationContext)
.orelsetrow(()->new RuntimeException(“无法定位Spring上下文”);
//通过context.getBean进行查找或将其存储为字段
}
}

这不起作用,至少在Jetty 9上是这样。applicationContext是null@JuanCalero-ApplicationContext也必须是静态的。这与在LoginModule中使用其他bean的原因相同——实例化是由JAAS执行的,因此Spring的依赖项注入不会生效。您是否尝试过SecurityContextHolder.getContext()?在您的jaas登录模块中返回什么?SecurityContextHolder是单例的,但它是在调用登录模块后填充的。它特定于Spring安全性,在调用LoginModule之后(而不是之前)包含有价值的信息。
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.spi.LoginModule;
import java.util.Map;

public class TokenLoginModule implements LoginModule {

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        ApplicationContext context = SpringContextHolder.getInstance()
            .flatMap(SpringContextHolder::getApplicationContext)
            .orElseThrow(() -> new RuntimeException("Unable to locate Spring context"));

       // lookup via context.getBean or just store it as a field
    }
}