Spring 安全性 UserDetailsService 抛出 UsernameNotFoundException
Spring Security UserDetailsService throws UsernameNotFoundException
在Spring安全性中,它们会自动将输入的用户名和密码与数据库保存的用户名和密码进行匹配。当密码不匹配时,它 return 是错误的凭据。但是,在我的代码中,据我所知,如果用户名也与数据库保存的用户名不匹配,他们应该 return 错误凭证。但是,在我的代码中,仅当用户名正确且密码错误时才会显示错误凭据,并且当用户名不在数据库中时会抛出 usernmaenotfoundexception。
我知道我在 loaduserByusername 中写了 usernamenotfoundexception。但是,是否应该首先从数据库中检查用户名是否匹配,如果错误则应该 returned 错误凭据?我从互联网上找到了 userdetailservice,大多数人都是这样写代码的。那我们怎么知道id不匹配.,?
非常感谢
UserDeatilSerivce.java
package com.group6.shopping.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.group6.shopping.members.dao.MembersDAO;
import org.springframework.ui.Model;
public class CustomMemDetailsService implements UserDetailsService{
@Autowired
MembersDAO membersDAO;
@Override
public UserDetails loadUserByUsername(String memId) {
System.out.println("loaduserByusername");
CustomMemDetails members = null;
try {
members = membersDAO.getMemById(memId);
if(members == null) {
throw new UsernameNotFoundException("username " + memId + " not found");
}
System.out.println("**************Found user***************");
System.out.println("id : " + members.getUsername());
return members;
} catch (Exception e) {
e.printStackTrace();
}
return members;
}
}
安全-context.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<security:http pattern="/resources/**" security="none"/>
<security:http>
<security:intercept-url pattern="/everyone/**" access="permitAll"/>
<security:intercept-url pattern="/member/**" access="hasRole('ROLE_MEMBER')"/>
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login login-page="/everyone/login"
login-processing-url="/everyone/login/loginProcess"
default-target-url="/"
authentication-failure-handler-ref="loginFailureHandler"/>
<!-- 최대 한 개의 세션만 생성되도록 -->
<security:session-management invalid-session-url="/everyone/login">
<security:concurrency-control max-sessions="1"
expired-url="/everyone/login"
error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customMemService">
<security:password-encoder hash="bcrypt"/>
</security:authentication-provider>
</security:authentication-manager>
<bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<bean id="loginFailureHandler" class="com.group6.shopping.security.LoginFailureHandler"/>
<context:component-scan base-package="com.group6.shopping.security" />
<bean id="customMemService" class="com.group6.shopping.security.CustomMemDetailsService" />
</beans>
LoginFailureHandler.java
package com.group6.shopping.security;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String msg = "";
if(exception instanceof UsernameNotFoundException){
System.out.println("username error");
msg = "Wrong id or password. Please re-enter";
}else if (exception instanceof BadCredentialsException){
System.out.println("bad credential");
msg = "Wrong id or password. Please re-enter";
}
request.setAttribute("msg", msg);
request.getRequestDispatcher("/everyone/login?error").forward(request, response);
}
}
我想念对 spring 安全流程的理解。它实际上是在 userdetailservice 为 运行 之后检查 id 和 password。所以,我只是删除了 throws new UsernameNotFoundException 和 return new CustomMemDetails();
然后在登录失败 handler.java 时检查异常是 DisabledException
在Spring安全性中,它们会自动将输入的用户名和密码与数据库保存的用户名和密码进行匹配。当密码不匹配时,它 return 是错误的凭据。但是,在我的代码中,据我所知,如果用户名也与数据库保存的用户名不匹配,他们应该 return 错误凭证。但是,在我的代码中,仅当用户名正确且密码错误时才会显示错误凭据,并且当用户名不在数据库中时会抛出 usernmaenotfoundexception。
我知道我在 loaduserByusername 中写了 usernamenotfoundexception。但是,是否应该首先从数据库中检查用户名是否匹配,如果错误则应该 returned 错误凭据?我从互联网上找到了 userdetailservice,大多数人都是这样写代码的。那我们怎么知道id不匹配.,?
非常感谢
UserDeatilSerivce.java
package com.group6.shopping.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.group6.shopping.members.dao.MembersDAO;
import org.springframework.ui.Model;
public class CustomMemDetailsService implements UserDetailsService{
@Autowired
MembersDAO membersDAO;
@Override
public UserDetails loadUserByUsername(String memId) {
System.out.println("loaduserByusername");
CustomMemDetails members = null;
try {
members = membersDAO.getMemById(memId);
if(members == null) {
throw new UsernameNotFoundException("username " + memId + " not found");
}
System.out.println("**************Found user***************");
System.out.println("id : " + members.getUsername());
return members;
} catch (Exception e) {
e.printStackTrace();
}
return members;
}
}
安全-context.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<security:http pattern="/resources/**" security="none"/>
<security:http>
<security:intercept-url pattern="/everyone/**" access="permitAll"/>
<security:intercept-url pattern="/member/**" access="hasRole('ROLE_MEMBER')"/>
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login login-page="/everyone/login"
login-processing-url="/everyone/login/loginProcess"
default-target-url="/"
authentication-failure-handler-ref="loginFailureHandler"/>
<!-- 최대 한 개의 세션만 생성되도록 -->
<security:session-management invalid-session-url="/everyone/login">
<security:concurrency-control max-sessions="1"
expired-url="/everyone/login"
error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customMemService">
<security:password-encoder hash="bcrypt"/>
</security:authentication-provider>
</security:authentication-manager>
<bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<bean id="loginFailureHandler" class="com.group6.shopping.security.LoginFailureHandler"/>
<context:component-scan base-package="com.group6.shopping.security" />
<bean id="customMemService" class="com.group6.shopping.security.CustomMemDetailsService" />
</beans>
LoginFailureHandler.java
package com.group6.shopping.security;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String msg = "";
if(exception instanceof UsernameNotFoundException){
System.out.println("username error");
msg = "Wrong id or password. Please re-enter";
}else if (exception instanceof BadCredentialsException){
System.out.println("bad credential");
msg = "Wrong id or password. Please re-enter";
}
request.setAttribute("msg", msg);
request.getRequestDispatcher("/everyone/login?error").forward(request, response);
}
}
我想念对 spring 安全流程的理解。它实际上是在 userdetailservice 为 运行 之后检查 id 和 password。所以,我只是删除了 throws new UsernameNotFoundException 和 return new CustomMemDetails(); 然后在登录失败 handler.java 时检查异常是 DisabledException