Spring Security Login不会在身份验证后导航

时间:2013-11-22 13:44:45

标签: jsf spring-mvc spring-security

我需要一些帮助。 你能告诉我Spring Security项目有什么问题吗? 这是我的 web.xml:

      <display-name>Spring Project</display-name>

        <welcome-file-list>
                <welcome-file>login.xhtml</welcome-file>
        </welcome-file-list>


        <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/applicationContext.xml</param-value>
        </context-param>

        <context-param>
                <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                <param-value>.xhtml</param-value>
        </context-param>


        <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        <servlet>
                <servlet-name>Resources Servlet</servlet-name>
                <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
                <load-on-startup>0</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>Resources Servlet</servlet-name>
                <url-pattern>/resources/*</url-pattern>
        </servlet-mapping>

        <servlet>
                <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <init-param>
                        <param-name>contextConfigLocation</param-name>
                        <param-value></param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
                <url-pattern>/app/*</url-pattern>
        </servlet-mapping>

        <servlet>
                <servlet-name>Faces Servlet</servlet-name>
                <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>Faces Servlet</servlet-name>
                <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>

        <filter>
                <filter-name>charEncodingFilter</filter-name>
                <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
                <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        </filter>

    <filter-mapping>
        <filter-name>charEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring security filters -->

    <filter>
                <filter-name>springSecurityFilterChain</filter-name>
                <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>

        <filter-mapping>
                <filter-name>springSecurityFilterChain</filter-name>
                <url-pattern>/*</url-pattern>
                <dispatcher>REQUEST</dispatcher>
                <dispatcher>FORWARD</dispatcher>
        </filter-mapping>

</web-app>

安全-config.xml中

 <security:http auto-config="true">
           <security:form-login login-page="/login.xhtml" authentication-failure-url="/loginfailed.xhtml" default-target-url="/succes.xhtml"  />
           <security:logout logout-url="/app/logout" logout-success-url="/app/main" />
    </security:http>


      <security:authentication-manager>
                <security:authentication-provider user-service-ref="userService">
                        <security:password-encoder hash="md5" />
                </security:authentication-provider>
      </security:authentication-manager>


     <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <property name="userDetailsService" ref="userService" />
                <property name="hideUserNotFoundExceptions" value="false" />
     </bean>

      <bean id="authenticationManager"   class="org.springframework.security.authentication.ProviderManager">
                <constructor-arg>
                        <ref local="daoAuthenticationProvider" />
                </constructor-arg>
     </bean>

</beans>

这是我的登录页面。

 <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui"
                template="/WEB-INF/templates/general.xhtml">

        <ui:define name="title"><h:outputText value="Please Sign In" /></ui:define>
        <ui:define name="header"><h:outputText value="Please Sign In" /></ui:define>


         <ui:define name="content">
             <h:form id="loginForm" prependId="false">
                     <p:fieldset styleClass="fieldset" legend="Authentication Form">
                             <p:focus />
                             <p:messages id="messages" />

                             <h:panelGrid id="logPanelGrid" style="margin: 0 auto; margin-top: 25px; text-align: right" cellspacing="8" columns="3">
                                        <h:panelGroup>
                                                <h:outputText value="User Name:" />
                                                <h:outputText style="color:red" value="*  " />
                                        </h:panelGroup>
                                        <p:inputText id="userName" value="#{userManagedBean.userName}" required="true" label="User Name" title="Enter your User Name!" />
                                        <h:panelGroup>
                                                <p:message id="userNameMsg" for="userName" />
                                                <p:tooltip for="userName" styleClass="tooltip" showEvent="focus" hideEvent="blur" />
                                        </h:panelGroup>

                                        <h:panelGroup>
                                                <h:outputText value="Enter Password:" />
                                                <h:outputText style="color:red" value="*  " />
                                        </h:panelGroup>
                                        <p:password id="pass" value="#{userManagedBean.password}" required="true" label="Password" title="Please enter a password!" />
                                        <h:panelGroup>
                                                <p:message id="passMsg" for="pass" />
                                                <p:tooltip for="pass" styleClass="tooltip" showEvent="focus" hideEvent="blur" />
                                        </h:panelGroup>



                                     <p:commandButton id="submitButton"  update="logPanelGrid,messages" action="#{userManagedBean.doLogin()}"  value="SignIn" />

                             </h:panelGrid>
                     </p:fieldset>
             </h:form>
        </ui:define> 

 </ui:composition>      

对于实现身份验证,我使用doLogin()方法创建UserManagedbean。

 package com.app.managed;

    import javax.faces.bean.ViewScoped;
    import javax.inject.Inject;

    import org.springframework.stereotype.Component;

    import com.app.model.UserEntity;
    import com.app.service.UserService;

    @Component
    @ViewScoped
    public class UserManagedBean {

     public UserManagedBean(){
         System.out.println("Just for test, usermanagedbean nstantiated");
     }
     @Inject
     private UserService userService;

     @Inject 
     private UserAuthenticationProviderServiceImpl userAuth;

     private UserEntity user;

     String userName;
     String password;


    public UserEntity getUser() {
         return user;
    }

    public void setUser(UserEntity user) {
         this.user = user;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean doLogin() {
        UserEntity user = userService.loadUserEntityByUsername(userName);
        return userAuth.processUserAuthentication(user);
    }



    }

我也创建了UserAuthenticationProviderService

package com.app.managed;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import com.app.model.UserEntity;


/**
 * Provides processing service to set user authentication session
 * 
 * @author Arthur Vin
 */
@Service("userAuthenticationProviderServiceImpl")
public class UserAuthenticationProviderServiceImpl implements UserAuthenticationProviderService {

        private AuthenticationManager authenticationManager;

        /**
         * Process user authentication
         * 
         * @param user
         * @return
         */
        public boolean processUserAuthentication(UserEntity user) {

                try {
                        System.out.println("11111");
                        Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
                        System.out.println("user.getUserName(), user.getPassword()" + user.getUserName() + " " + user.getPassword() );

                    Authentication result = authenticationManager.authenticate(request);
                    SecurityContextHolder.getContext().setAuthentication(result);

                    return true;
            } catch(AuthenticationException e) {
                    FacesContext.getCurrentInstance().addMessage(null, 
                                    new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), "Sorry!"));

                    return false;
            }
    }

    public AuthenticationManager getAuthenticationManager() {
            return authenticationManager;
    }

    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
            this.authenticationManager = authenticationManager;
    }

}

AND Implements UserDeatailsS​​ervice

  package com.app.service;

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.ResourceBundle;

    import javax.faces.application.FacesMessage;
    import javax.faces.context.FacesContext;
    import javax.faces.event.AjaxBehaviorEvent;

    import org.primefaces.component.inputtext.InputText;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;

    import com.app.dao.UserDao;
    import com.app.model.UserEntity;
    import com.app.service.intf.UserServiceIntf;


    /**
     * Service providing service methods to work with user data and entity.
     * 
     * @author Arthur Vin
     */
    @Service("userService")
    public class UserService implements UserServiceIntf, UserDetailsService {
            @Autowired
            private UserDao userDao;

        /**
         * Check user name availability. UI ajax use.
         * 
         * @param ajax event
         * @return
         */
        public boolean checkAvailable(AjaxBehaviorEvent event) {

                InputText inputText = (InputText) event.getSource();
                String value = (String) inputText.getValue();

                boolean available = userDao.checkAvailable(value);

                if (!available) {
                        FacesMessage message = constructErrorMessage(null, String.format(getMessageBundle().getString("userExistsMsg"), value));
                        getFacesContext().addMessage(event.getComponent().getClientId(), message);
                } else {
                        FacesMessage message = constructInfoMessage(null, String.format(getMessageBundle().getString("userAvailableMsg"), value));
                        getFacesContext().addMessage(event.getComponent().getClientId(), message);
                }

                return available;
        }

        /**
         * Construct UserDetails instance required by spring security
         */
        public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

                UserEntity user = userDao.loadUserByUserName(userName);

                if (user == null) {
                    System.out.println("NUL11!!");
                        throw new UsernameNotFoundException(String.format(getMessageBundle().getString("badCredentials"), userName));

                }

                Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
                System.out.println("user.getUserName()"+ user.getUserName());
                User userDetails = new User(user.getUserName(), user.getPassword(), authorities);

                return userDetails;
        }

        /**
         * Retrieves full User record from database by user name
         * 
         * @param userName
         * @return UserEntity
         */
        public UserEntity loadUserEntityByUsername(String userName) {
                return userDao.loadUserByUserName(userName);
        }

        protected FacesMessage constructErrorMessage(String message, String detail){
                return new FacesMessage(FacesMessage.SEVERITY_ERROR, message, detail);
        }

        protected FacesMessage constructInfoMessage(String message, String detail) {
                return new FacesMessage(FacesMessage.SEVERITY_INFO, message, detail);
        }

        protected FacesMessage constructFatalMessage(String message, String detail) {
                return new FacesMessage(FacesMessage.SEVERITY_FATAL, message, detail);
        }

        protected FacesContext getFacesContext() {
                return FacesContext.getCurrentInstance();
        }

        protected ResourceBundle getMessageBundle() {
                return ResourceBundle.getBundle("message-labels");
        }

        public UserDao getUserDao() {
                return userDao;
        }

        public void setUserDao(UserDao userDao) {
                this.userDao = userDao;
        }

    }

我也有UserEntity类,其中包含用户名密码列。   那么我点击登录按钮上的login.xhtml页面,右侧的用户名和密码页重新加载,没有别的。    有人能告诉我,我做错了吗?

1 个答案:

答案 0 :(得分:0)

您的doLogin()方法违反了p:commandButton上的操作属性合同:

public boolean doLogin() {
        UserEntity user = userService.loadUserEntityByUsername(userName);
        return userAuth.processUserAuthentication(user);
    }

此方法返回boolean。如果您想在其他地方导航,则应返回String

 public String doLogin() {
        UserEntity user = userService.loadUserEntityByUsername(userName);
        boolean result = userAuth.processUserAuthentication(user);

        if (result) {
            return "path/To/Landing/Page";
        }

          //result was false - handle login error condition

          //keep the view scope bean alive and don't change the page
          return null;
    }

action方法触发后,返回的String是用户之后应该访问的视图的路径。在您的情况下,我怀疑这将根据身份验证的结果而有所不同,但目前,您没有。

由于您的方法签名,无论是否有任何Spring Security内容,您都可以在最初的位置结束。