Home > Software design >  Spring Security UserDetailsService throws UsernameNotFoundException
Spring Security UserDetailsService throws UsernameNotFoundException

Time:03-28

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"  />
    <bean id="loginFailureHandler" />

    <context:component-scan base-package="com.group6.shopping.security" />
    <bean id="customMemService"  />
</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);
    }
}

CodePudding user response:

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

  • Related