登录后弹簧安全性的重定向错误

时间:2014-01-04 17:41:54

标签: java spring java-ee spring-mvc spring-security

修改

我的猜测是,原始网址请求首先是“/”,因此在成功登录时,用户登陆到“/”。

如果用户在登录前输入了site.com/someOtherUrl,则登录成功后他将登陆site.com/someOtherUrl。如何解决/

编辑结束 -

当用户来时,

mysite.comlocalhosr:8080

他登陆/login页面然后输入凭据并按下登录按钮。

现在他实际上已登录。他应该降落在/users/home

但他登陆 /

此时,当他登录时,他可以使用地址栏手动转到/users/home

不知情的用户(关于问题)会点击后退按钮并再次登录,然后按照他应该的方式登陆到正确的网址/users/home

问题是,为什么不是第一次?为什么他第一次登陆“/”而不是/ users / home尽管他已登录?

弹簧security.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
   http://www.springframework.org/schema/security
   http://www.springframework.org/schema/security/spring-security-3.1.xsd">

 <!-- This is where we configure Spring-Security  -->
 <security:http auto-config="true" use-expressions="true" access-denied-page="/loginfail" >

 <security:intercept-url pattern="/" access="permitAll"/>
 <security:intercept-url pattern="/favicon.ico" access="permitAll"/>  <!-- lolz -->
  <security:intercept-url pattern="/login" access="permitAll"/>
  <security:intercept-url pattern="/logout" access="permitAll"/>
  <security:intercept-url pattern="/loginfail" access="permitAll"/>
  <security:intercept-url pattern="/resources/**" access="permitAll"/>
  <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>



  <security:form-login
    login-page="/login"

    authentication-failure-url="/login?error=true"

    default-target-url="/users/home"/>
  <!-- authentication-failure-url="/loginfail?error=true" -->   


  <security:logout
    invalidate-session="true"
    logout-success-url="/login"
    logout-url="/logout"/>

 </security:http>


 <!-- Declare an authentication-manager to use a custom userDetailsService -->
 <security:authentication-manager>
         <security:authentication-provider user-service-ref="customUserDetailsService">
  <!--         <security:password-encoder ref="passwordEncoder"/>-->
         </security:authentication-provider>
 </security:authentication-manager>

 <!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database 
 <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
 -->
 <!-- A custom service where Spring will retrieve users and their corresponding access levels  -->
 <bean id="customUserDetailsService" class="web.service.common.CustomUserDetailsService"/>
   <!--For loging security activity-->
    <!--<bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener" />-->




</beans>

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <welcome-file-list>
        <!--<welcome-file>login</welcome-file> -->
        <welcome-file>login.jsp</welcome-file>
        <!--<welcome-file>redirect.jsp</welcome-file>-->
        <!--<welcome-file>WEB-INF/view/jsp/login/login.jsp</welcome-file>-->
    </welcome-file-list>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>springDispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcher</servlet-name>
        <url-pattern>/</url-pattern>

    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
<!--    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>-->



    <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>
    </filter-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml
            /WEB-INF/applicationContext.xml
        </param-value>
    </context-param>
</web-app>

CustomUserDetailsS​​ervice

package web.service.common;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
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.Repository;
import org.springframework.stereotype.Service;
import web.dao.UsersDAO;
import web.dao.impl.jpa.UsersDAOImpl;
import web.entity.Users;



@Service
public class CustomUserDetailsService implements UserDetailsService{

    //@Resource
   @Autowired
   private UsersDAO userDAO;


 /**
  * Retrieves a springUser record containing the springUser's credentials and access.
  */
 public UserDetails loadUserByUsername(String email)
   throws UsernameNotFoundException, DataAccessException {


  // Declare a null Spring User
  UserDetails springUser = null;


  try {
    System.out.println("the email passed from CustomUserDetailsService in method loadUserByUsername is: " +email);
   // Search database for a springUser that matches the specified email
   // You can provide a custom DAO to access your persistence layer
   // Or use JDBC to access your database
   // DbUser is our custom domain springUser. This is not the same as Spring's User
      System.out.println("debug ---- 1");
   Users dbUser = userDAO.getUserByLoginId(email);

   // Populate the Spring User object with details from the dbUser
   // Here we just pass the email, password, and access level
   // getAuthorities() will translate the access level to the correct role type
 System.out.println("debug ---- 2");
   springUser =  new User(
     dbUser.getEmail(),
     dbUser.getPassword().toLowerCase(),
     true,
     true,
     true,
     true,
     //getAuthorities(dbUser.getAccess()) );
     getAuthorities(2) );
 System.out.println("debug ---- 3");
  } catch (Exception e) {
   System.out.println("print Error in retrieving user");
   e.printStackTrace();
    System.out.println(e.getMessage());
   throw new UsernameNotFoundException("Error in retrieving user");
  }
   System.out.println("debug ---- 4");
  // Return springUser to Spring for processing.
  // Take note we're not the one evaluating whether this springUser is authenticated or valid
  // We just merely retrieve a springUser that matches the specified email
  return springUser;
 }

 /**
  * Retrieves the correct ROLE type depending on the access level, where access level is an Integer.
  * Basically, this interprets the access value whether it's for a regular springUser or admin.
  *
  * @param access an integer value representing the access of the springUser
  * @return collection of granted authorities
  */
  public Collection<GrantedAuthority> getAuthorities(Integer access) {
   // Create a list of grants for this springUser
   List<GrantedAuthority> authList = (List<GrantedAuthority>) new ArrayList<GrantedAuthority>(2);

   // All users are granted with ROLE_USER access
   // Therefore this springUser gets a ROLE_USER by default
   System.out.println("Grant ROLE_USER to this user");
   authList.add(new GrantedAuthorityImpl("ROLE_USER"));

   // Check if this springUser has admin access
   // We interpret Integer(1) as an admin springUser

//   if ( access.compareTo(1) == 0) {
//    // User has admin access
//    logger.debug("Grant ROLE_ADMIN to this user");
//    authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
//   }

   // Return list of granted authorities
   return authList;
   }

}

1 个答案:

答案 0 :(得分:4)

默认情况下,Spring Security会在登录后将用户重定向到他最初请求的URL(在您的情况下为/)。

您可以将always-use-default-target设置为true以禁用此行为:

<security:form-login
    login-page="/login"
    authentication-failure-url="/login?error=true"
    default-target-url="/users/home"
    always-use-default-target = "true"
/>