登录后spring security重定向不正确
Posted
技术标签:
【中文标题】登录后spring security重定向不正确【英文标题】:incorrect redirection of spring security after login 【发布时间】:2014-01-22 08:19:21 【问题描述】:编辑 --
我的猜测是最初的原始 url 请求是 "/" ,所以在成功登录后,用户将登陆到 "/" 。
如果用户在登录前输入了site.com/someOtherUrl,那么在登录成功后他将被登陆到site.com/someOtherUrl。如何解决/
编辑结束--
对于mysite.com
或localhosr:8080
,当有用户来访时,
他登陆/login
页面,然后输入凭据并按下登录按钮。
现在他实际上是登录了。他应该降落在/users/home
但他降落在/
此时,当他登录后,他可以通过地址栏手动转到/users/home
。
一个不知情的用户(关于这个问题)会点击返回按钮并再次登录,然后以他应该的方式登陆到正确的 url /users/home
页面
问题是,为什么不是第一次呢?为什么他第一次登陆“/”而不是/users/home,尽管他已经登录了?
spring-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>
CustomUserDetailsService
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;
【问题讨论】:
用户在被重定向到登录屏幕之前尝试输入的原始 url 是什么? 我不会使用默认目标网址。如果用户请求/some123Page,那么他将被重定向到登录页面,并且在成功登录后他应该被重定向回/some123Page。这不工作? (我想确保我理解这个案子) 【参考方案1】:默认情况下,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"
/>
【讨论】:
嗯..太好了。还有其他选择吗?因为如果用户请求了/some123Page
,那么他在任何情况下都登陆/home/users
会很烦人。但更烦人的是登陆"/"
如果是这样,你只需要处理对/
的请求并将它们重定向到/home/users
,它与Spring Security无关
我虽然可能有弹簧安全方式。反正。很大的帮助。谢谢以上是关于登录后spring security重定向不正确的主要内容,如果未能解决你的问题,请参考以下文章
成功登录后 Spring Boot Security 重定向 - 未定义
执行登录保存请求后,Spring Boot Security POST 重定向到登录页面