Spring security 如何通过ldap身份验证和授权对登录流应用安全性?

Spring security 如何通过ldap身份验证和授权对登录流应用安全性?,spring-security,spring-ldap,spring-webflow-2,spring-security-ldap,Spring Security,Spring Ldap,Spring Webflow 2,Spring Security Ldap,我用SpringWebflow2和SpringLDAP实现了一个登录servlet,用于用户身份验证。到目前为止一切正常 现在,我正在尝试在我的登录流中引入spring安全性。因此,遵循SpringWebFlowReferenceGuide版本2.4.0(第8节)和SpringSecurityLDAP部分指南,我调整了配置以保护流。特别是,我正在尝试为角色用户保护成功登录页面 我试图从ldap数据库中提取用户名、密码和用户角色,并使用这些信息在我的流中应用安全性。因此,我对我的项目进行了以下更改

我用SpringWebflow2和SpringLDAP实现了一个登录servlet,用于用户身份验证。到目前为止一切正常

现在,我正在尝试在我的登录流中引入spring安全性。因此,遵循SpringWebFlowReferenceGuide版本2.4.0(第8节)和SpringSecurityLDAP部分指南,我调整了配置以保护流。特别是,我正在尝试为角色用户保护成功登录页面

我试图从ldap数据库中提取用户名、密码和用户角色,并使用这些信息在我的流中应用安全性。因此,我对我的项目进行了以下更改:

  • 将安全属性添加到loginflow.xml中的DisplayLoginsAccess视图状态

  • 输入用户名和密码后,我有以下错误

    HTTP Status 500 - Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
    ________________________________________
    type Exception report   
    message Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
    description The server encountered an internal error that prevented it from fulfilling this request.
    exception 
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    root cause 
    org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
        org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:573)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:263)
        org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
        org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    root cause 
    java.lang.NullPointerException
        org.springframework.security.access.vote.RoleVoter.extractAuthorities(RoleVoter.java:115)
        org.springframework.security.access.vote.RoleVoter.vote(RoleVoter.java:96)
        org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:62)
        org.springframework.webflow.security.SecurityFlowExecutionListener.decide(SecurityFlowExecutionListener.java:109)
        org.springframework.webflow.security.SecurityFlowExecutionListener.stateEntering(SecurityFlowExecutionListener.java:74)
        org.springframework.webflow.engine.impl.FlowExecutionListeners.fireStateEntering(FlowExecutionListeners.java:144)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.setCurrentState(FlowExecutionImpl.java:373)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.setCurrentState(RequestControlContextImpl.java:189)
        org.springframework.webflow.engine.State.enter(State.java:191)
        org.springframework.webflow.engine.Transition.execute(Transition.java:228)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
        org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
        org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
        org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:105)
        org.springframework.webflow.engine.State.enter(State.java:194)
        org.springframework.webflow.engine.Transition.execute(Transition.java:228)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
        org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
        org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
        org.springframework.webflow.engine.ViewState.handleEvent(ViewState.java:231)
        org.springframework.webflow.engine.ViewState.resume(ViewState.java:195)
        org.springframework.webflow.engine.Flow.resume(Flow.java:537)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
        org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
        org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    

    我认为spring-config.xml中的身份验证提供程序设置与用于身份验证和授权的java类不匹配。如何从ldap中成功检索角色?

    我通过ldapAuthenticationManager注入解决了这个问题

    我在spring config.xml身份验证管理器中添加了一个authManager别名和一个用于映射java类的属性:

    ...
    
    <bean id="loginService" class="com.folkture.login.LoginService">
            <property name="ldapTemplate" ref="ldapTemplate" />
            <property name="ldapAuthenticationManager" ref="authManager" />
        </bean>
    
    ...
    
        <s:authentication-manager alias="authManager">
            <s:ldap-authentication-provider
                group-search-filter="(member={0})"
                group-search-base="ou=groups"
                group-role-attribute="cn"
                role-prefix="ROLE_"
                user-search-filter="(cn={0})"
                user-search-base="ou=users"
                server-ref="contextSource" />
        </s:authentication-manager>
    ...
    
    并使用ldapAuthenticationManager更改了登录方法。Authentication方法:

    public boolean login(String username, String password){
        Authentication authenticatedUser = null;
        Authentication auth = new UsernamePasswordAuthenticationToken(username, password);
        authenticatedUser = ldapAuthenticationManager.authenticate(auth);
    SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    System.out.println("authenticatedUser role" + authenticatedUser.getAuthorities());
        return true;
        }
    
    package com.folkture.login;
    
    import javax.naming.directory.DirContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.ldap.NamingException;
    import org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback;
    import org.springframework.ldap.core.DirContextOperations;
    import org.springframework.ldap.core.LdapEntryIdentification;
    import org.springframework.ldap.core.LdapTemplate;
    import org.springframework.ldap.filter.AndFilter;
    import org.springframework.ldap.filter.EqualsFilter;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.ldap.authentication.LdapAuthenticator;
    import org.springframework.stereotype.Service;
    
    @Service
    public class LoginService implements LdapAuthenticator{
    @Autowired
    private LdapTemplate ldapTemplate;
    
    public LoginService() {
        super();
    }
    
    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
        System.out.println("setLdapTemplate "+ ldapTemplate);
    }
    
    public String performLogin(LoginCredentials loginCredentials) throws Exception{
    
        if(login(loginCredentials.getLoginName(),loginCredentials.getPassword())) 
    
        {
            System.out.println("autenticato!");
            return "success";
        } else {
            throw new IncorrectLoginCredentialsException();
        }
    }
    
    public boolean login(String username, String password) throws Exception{
    
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectclass", "inetOrgPerson")).and(new EqualsFilter("cn", username));
    
        if(ldapTemplate.authenticate("ou=users", filter.toString(), password, contextCallback))
            return true;
        return false;
    
    }
    
    AuthenticatedLdapEntryContextCallback contextCallback = new AuthenticatedLdapEntryContextCallback() {
        @SuppressWarnings("deprecation")
        public void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
            try {
                try {
                    ctx.lookup(ldapEntryIdentification.getRelativeDn());
                } catch (javax.naming.NamingException e) {
                    e.printStackTrace();
                }
            }
            catch (NamingException e) {
                throw new RuntimeException("Failed to lookup " + ldapEntryIdentification.getRelativeDn(), e);
            }
        }
    };
    
    @Override
    public DirContextOperations authenticate(Authentication authentication) {
        // TODO Auto-generated method stub
        return null;
        }
    }
    
    HTTP Status 500 - Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
    ________________________________________
    type Exception report   
    message Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
    description The server encountered an internal error that prevented it from fulfilling this request.
    exception 
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    root cause 
    org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'performLoginAction' of flow 'loginFlow'
        org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:573)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:263)
        org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
        org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    root cause 
    java.lang.NullPointerException
        org.springframework.security.access.vote.RoleVoter.extractAuthorities(RoleVoter.java:115)
        org.springframework.security.access.vote.RoleVoter.vote(RoleVoter.java:96)
        org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:62)
        org.springframework.webflow.security.SecurityFlowExecutionListener.decide(SecurityFlowExecutionListener.java:109)
        org.springframework.webflow.security.SecurityFlowExecutionListener.stateEntering(SecurityFlowExecutionListener.java:74)
        org.springframework.webflow.engine.impl.FlowExecutionListeners.fireStateEntering(FlowExecutionListeners.java:144)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.setCurrentState(FlowExecutionImpl.java:373)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.setCurrentState(RequestControlContextImpl.java:189)
        org.springframework.webflow.engine.State.enter(State.java:191)
        org.springframework.webflow.engine.Transition.execute(Transition.java:228)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
        org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
        org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
        org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:105)
        org.springframework.webflow.engine.State.enter(State.java:194)
        org.springframework.webflow.engine.Transition.execute(Transition.java:228)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)
        org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)
        org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)
        org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
        org.springframework.webflow.engine.ViewState.handleEvent(ViewState.java:231)
        org.springframework.webflow.engine.ViewState.resume(ViewState.java:195)
        org.springframework.webflow.engine.Flow.resume(Flow.java:537)
        org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
        org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
        org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:228)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    
    ...
    
    <bean id="loginService" class="com.folkture.login.LoginService">
            <property name="ldapTemplate" ref="ldapTemplate" />
            <property name="ldapAuthenticationManager" ref="authManager" />
        </bean>
    
    ...
    
        <s:authentication-manager alias="authManager">
            <s:ldap-authentication-provider
                group-search-filter="(member={0})"
                group-search-base="ou=groups"
                group-role-attribute="cn"
                role-prefix="ROLE_"
                user-search-filter="(cn={0})"
                user-search-base="ou=users"
                server-ref="contextSource" />
        </s:authentication-manager>
    ...
    
    ...
        @Autowired
        @Qualifier("authManager")
        private AuthenticationManager ldapAuthenticationManager;
    
    public void setLdapAuthenticationManager(AuthenticationManager ldapAuthenticationManager) {
            this.ldapAuthenticationManager = ldapAuthenticationManager;
        }
    
    public boolean login(String username, String password){
        Authentication authenticatedUser = null;
        Authentication auth = new UsernamePasswordAuthenticationToken(username, password);
        authenticatedUser = ldapAuthenticationManager.authenticate(auth);
    SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    System.out.println("authenticatedUser role" + authenticatedUser.getAuthorities());
        return true;
        }