Spring security - 未调用自定义 userDetailsS​​ervice 实现

Posted

技术标签:

【中文标题】Spring security - 未调用自定义 userDetailsS​​ervice 实现【英文标题】:Spring security - custom userDetailsService implemenation not getting called 【发布时间】:2016-03-09 16:47:59 【问题描述】:

尝试使用自定义 userDetailsS​​ervice 学习 Spring Security 并面临以下问题

当访问受限页面(/admin 或 /user)时,spring security 会启动并显示登录页面。 但是在使用正确的用户名和密码提交登录页面后,在调用我的自定义 userDetailsS​​ervice 实现中的 loadUserByUsername 方法之前直接显示拒绝访问页面。

在日志中,只有 org.springframework.security.access.AccessDeniedException 异常 - 在访问受限页面时,没有其他异常。

代码

@Controller
public class TestController 

    @RequestMapping("/home")
    public String getHomePage() 
        return "home";
    


    @RequestMapping(value="/user")
    public String getUserPage() 
        return "user";
    

    @RequestMapping(value="/admin")
    public String getAdminPage() 
        return "admin";
    

安全配置:

<http auto-config="true"  use-expressions="true">
        <intercept-url pattern="/" access="permitAll"/>
        <intercept-url pattern="/login" access="permitAll"/>
        <intercept-url pattern="/logout" access="permitAll"/>
        <intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/>
        <intercept-url pattern="/user" access="hasRole('ROLE_USER')"/>
        <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')"/>

        <form-login login-page="/login"
            username-parameter="tmp_usrnm"
            password-parameter="tmp_pwd" 
            authentication-failure-url="/login/failure" 
            default-target-url="/abcd"/>

        <access-denied-handler error-page="/denied"/>

        <logout invalidate-session="true" 
            logout-success-url="/logout/success" 
            logout-url="/logout"/>
    </http>

    <authentication-manager>
        <authentication-provider user-service-ref="customUserDetailsService">
            <password-encoder hash="md5"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="customUserDetailsService" class="com.krishnan.balaji.mc.service.CustomUserDetailsService">
        <beans:property name="userRepository">
            <beans:bean class="com.krishnan.balaji.mc.repos.UserRepositoryImpl"></beans:bean>   
        </beans:property>
    </beans:bean>

登录表格:

<!--<form class="login-form" action=<c:url value="j_spring_security_check"/> method="post" >-->
<form action=<c:url value="/login"/> method="post" >
            <input id="j_username" name="tmp_usrnm" size="20" maxlength="50" type="text"/>
            <input id="j_password" name="tmp_pwd" size="20" maxlength="50" type="password"/>
            <p><input type="submit" value="Login"/></p>
</form> 

控制器为登录/注销/访问被拒绝页面提供服务

@Controller
public class UserAccessController 

    @RequestMapping("/login")
    public String login(Model model, @RequestParam(required=false) String message) 
        model.addAttribute("message", message);
        System.out.println("serving login page");
        return "access/login";
    

    @RequestMapping(value = "/denied")
    public String denied() 
        System.out.println("serving access denied page");
        return "access/denied";
    

    @RequestMapping(value = "/login/failure")
    public String loginFailure() 
        System.out.println("serving failed login page");
        String message = "Login Failure!";
        return "redirect:/login?message="+message;
    

    @RequestMapping(value = "/logout/success")
    public String logoutSuccess() 
        System.out.println("serving logout page");
        String message = "Logout Success!";
        return "redirect:/login?message="+message;
    

CustomUserDetailsS​​ervice

@Service
public class CustomUserDetailsService implements UserDetailsService 

    private UserRepository userRepository;;

    @Transactional(readOnly = true)
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException 
        System.out.println("loadUserByUsername called");
        try 
            com.krishnan.balaji.mc.model.User domainUser = userRepository
                    .getUserByUserName(username);

            boolean enabled = true;
            boolean accountNonExpired = true;
            boolean credentialsNonExpired = true;
            boolean accountNonLocked = true;

            return new User(domainUser.getUsername(), domainUser.getPassword()
                    .toLowerCase(), enabled, accountNonExpired,
                    credentialsNonExpired, accountNonLocked,
                    getAuthorities(domainUser.getRole().getRole()));

         catch (Exception e) 
            throw new RuntimeException(e);
        
    

    public Collection<? extends GrantedAuthority> getAuthorities(Integer role) 
        List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
        return authList;
    

    public List<String> getRoles(Integer role) 
        List<String> roles = new ArrayList<String>();

        if (role.intValue() == 1) 
            roles.add("ROLE_USER");
            roles.add("ROLE_ADMIN");

         else if (role.intValue() == 2) 
            roles.add("ROLE_USER");
        

        return roles;
    

    public static List<GrantedAuthority> getGrantedAuthorities(
            List<String> roles) 
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (String role : roles) 
            authorities.add(new SimpleGrantedAuthority(role));
        
        return authorities;
    

    public UserRepository getUserRepository() 
        return userRepository;
    

    public void setUserRepository(UserRepository userRepository) 
        this.userRepository = userRepository;
    


【问题讨论】:

【参考方案1】:

http 的 Spring Security 配置中,您应该更改以下内容:

default-target-url="/abcd"

类似

default-target-url="/"

或您定义的任何其他内容。

default-target-url 定义了在登录过程succeeds 时默认 去哪里。 确保定义所有必要的intercept-url,从最具体到最通用

【讨论】:

也尝试将其更改为 /home.. 无论如何,这只有在登录过程成功的情况下 - 在我的情况下,甚至没有调用 userdetailsS​​ervice

以上是关于Spring security - 未调用自定义 userDetailsS​​ervice 实现的主要内容,如果未能解决你的问题,请参考以下文章

Spring security - 未调用自定义 userDetailsS​​ervice 实现

Spring Security:未调用自定义 UserDetailsS​​ervice(使用 Auth0 身份验证)

未调用 Spring Security j_spring_security_check

Spring安全性j_spring_security_check调用给出404未找到错误[关闭]

Spring Boot Security 自定义登录页面未加载

Spring Security 未路由到自定义登录页面 404 错误