Java 登录后spring security的重定向不正确
编辑-- 我猜最初的url请求是“/”,所以在成功登录时,用户登陆到“/” 如果用户在登录前已输入site.com/someOtherUrl,则在登录成功后将登录到site.com/someOtherUrl。如何解决这个问题/ 编辑结束-- 对于Java 登录后spring security的重定向不正确,java,spring,jakarta-ee,spring-mvc,spring-security,Java,Spring,Jakarta Ee,Spring Mvc,Spring Security,编辑-- 我猜最初的url请求是“/”,所以在成功登录时,用户登陆到“/” 如果用户在登录前已输入site.com/someOtherUrl,则在登录成功后将登录到site.com/someOtherUrl。如何解决这个问题/ 编辑结束-- 对于mysite.com或localhosr:8080当用户到来时 他登陆到/login页面,然后输入凭证并按下登录按钮 现在他实际上已经登录了。他应该降落在/users/home 但他降落在/ 此时,当他登录时,他可以使用地址栏手动转到/users/hom
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>
login.jsp
org.springframework.web.context.ContextLoaderListener
springDispatcher
org.springframework.web.servlet.DispatcherServlet
1.
springDispatcher
/
30
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
/*
上下文配置位置
/WEB-INF/spring-security.xml
/WEB-INF/applicationContext.xml
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;
}
}
包web.service.common;
导入java.util.ArrayList;
导入java.util.Collection;
导入java.util.List;
导入javax.annotation.Resource;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.dao.DataAccessException;
导入org.springframework.security.core.GrantedAuthority;
导入org.springframework.security.core.userdetails.User;
导入org.springframework.security.core.userdetails.userdetails;
导入org.springframework.security.core.userdetails.userdetails服务;
导入org.springframework.security.core.userdetails.UsernameNotFoundException;
导入org.springframework.stereotype.Repository;
导入org.springframework.stereotype.Service;
导入web.dao.UsersDAO;
导入web.dao.impl.jpa.UsersDAOImpl;
导入web.entity.Users;
@服务
公共类CustomUserDetailsService实现UserDetailsService{
//@资源
@自动连线
私有用户dao userDAO;
/**
*检索包含springUser凭据和访问权限的springUser记录。
*/
公共用户详细信息loadUserByUsername(字符串电子邮件)
抛出UsernameNotFoundException、DataAccessException{
//声明一个空的Spring用户
UserDetails-springUser=null;
试一试{
System.out.println(“方法loadUserByUsername中从CustomUserDetailsService传递的电子邮件为:“+email”);
//在数据库中搜索与指定电子邮件匹配的springUser
//您可以提供一个自定义DAO来访问持久层
//或者使用JDBC访问您的数据库
//DbUser是我们的自定义域springUser。这与Spring的用户不同
System.out.println(“debug---1”);
Users dbUser=userDAO.getUserByLoginId(电子邮件);
//使用dbUser中的详细信息填充Spring用户对象
//这里我们只传递电子邮件、密码和访问级别
//getAuthories()将访问级别转换为正确的角色类型
System.out.println(“debug---2”);
springUser=新用户(
dbUser.getEmail(),
dbUser.getPassword().toLowerCase(),
符合事实的
符合事实的
符合事实的
符合事实的
//getAuthories(dbUser.getAccess());
(二),;
System.out.println(“debug---3”);
}捕获(例外e){
System.out.println(“检索用户时出现打印错误”);
e、 printStackTrace();
System.out.println(e.getMessage());
抛出新的UsernameNotFoundException(“检索用户时出错”);
}
System.out.println(“debug---4”);
//将springUser返回到Spring进行处理。
//请注意,我们不是评估此springUser是否经过身份验证或有效的人
//我们只需检索与指定电子邮件匹配的springUser
返回用户;
}
/**
*根据访问级别检索正确的角色类型,其中访问级别为整数。
*基本上,无论是普通springUser还是admin,这都会解释访问值。
*
*@param access表示springUser访问权限的整数值
*@已授予权限的返回集合
*/
公共集合权限(整数访问){
//为此springUser创建授权列表
List authList=(List)新数组列表(2);
//所有用户都被授予角色\用户访问权限
//因此,默认情况下,此springUser获得一个角色\用户
System.out.println(“将角色_用户授予此用户”);
add(新授予的authorityImpl(“角色用户”);
//检查此springUser是否具有管理员权限
//我们将整数(1)解释为管理员用户
//if(访问比较到(1)==0){
////用户具有管理员权限
//debug(“向该用户授予角色_ADMIN”);
//add(新授予的authorityImpl(“角色\管理员”);
// }
//已授予权限的返回列表
返回authList;
}
}
默认情况下,Spring Security会在用户登录后将用户重定向到他最初请求的URL(在您的情况下为/
)
您可以将始终使用默认目标设置为true
以禁用此行为:
<security:form-login
login-page="/login"
authentication-failure-url="/login?error=true"
default-target-url="/users/home"
always-use-default-target = "true"
/>
默认情况下,弹簧安全红色