Spring Security UserDetailsS​​ervice 抛出 UsernameNotFoundException

发布于 2025-01-12 06:44:18 字数 5557 浏览 0 评论 0原文

在Spring Security中,它们会自动将输入的用户名和密码与数据库保存的用户名和密码进行匹配。当密码不匹配时,它会返回错误的凭据。但是,在我的代码中,只要我知道,如果用户名也不与数据库保存的用户名匹配,它们应该返回错误的凭据。但是,在我的代码中,仅当用户名正确且密码错误时才会显示错误的凭据,并且当用户名不在数据库中时,它会抛出 usernmaenotfoundException。

我知道我在 loaduserByusername 中写了 usernamenotfoundexception。但是,是否应该首先从数据库检查用户名是否匹配,如果错误则应返回错误的凭据?我从互联网上找到了 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;
        
    }

}

security-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);
    }
}

In the Spring Security, they automatically match input username and password with the DB saved username and password. It returns bad credential when password is not matched. However, in my code, as long as I know, if the username also does not match with DB saved username they should return bad credential. However, in my code, bad credential are shown only when username is correct and password is wrong and when username is not in DB it throws usernmaenotfoundexception.

I know I wrote usernamenotfoundexception in loaduserByusername. However, should it be first to check from DB whether username is matched and if it is wrong then bad credentials should be returned? I found userdetailservice from internet and most of people wrote the code this way. Then how should we know id not matched.,,?

Thank you so much

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;
        
    }

}

security-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);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酷炫老祖宗 2025-01-19 06:44:18

我对 Spring Security 流程缺乏了解。它实际上在 userdetailservice 运行后检查 id 和密码。所以,我只是删除抛出新的 UsernameNotFoundException 并返回新的 CustomMemDetails();
然后在登录失败 handler.java 中检查异常是否为 DisabledException

I had miss understanding of spring security flow. It actually checks id and password after userdetailservice is ran. So, I just delete throws new UsernameNotFoundException and return new CustomMemDetails();
then in login failure handler.java just check exception is DisabledException

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文