java - Spring security Remember me 和自定义身份验证提供程序

标签 java spring spring-mvc authentication spring-security

Spring 问题请记住我

在我的 Spring 安全应用程序中,我有自定义身份验证提供程序,可以对自定义身份验证对象进行身份验证并返回自定义身份验证对象,并且身份验证工作正常,但我对 Spring Remember me 服务有问题,它无法正常工作

但是当我通过正常的 Spring Security 进行身份验证时,通过使用 UserDetailService 然后“记住我”效果很好,我的代码如下

package com.websopti.wotms.auth;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import com.websopti.wotms.entity.User;
import com.websopti.wotms.enums.ErrorKey;
import com.websopti.wotms.service.UserService;

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    public UserService userService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        String email = authentication.getPrincipal().toString();
        String password = authentication.getCredentials().toString();

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

        String username = null;

        try {
            username = userService.authenticate(email, password);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(username != null && !username.equals("0")){

            User user = userService.findByEmail(email);

            if (user != null) {

                authorities.add(new SimpleGrantedAuthority(user.getRole().name()));
                return (new UsernamePasswordAuthenticationToken(user, null, authorities));

            } else {

                User newUser = new User();
                newUser.setName(username);
                newUser.setEmail(email);
                newUser.setPassword(password);

                userService.register(newUser);

                newUser = userService.findById(newUser.getId());                
                authorities.add(new SimpleGrantedAuthority(newUser.getRole().name()));

                return (new UsernamePasswordAuthenticationToken(newUser, null, authorities));
            }

        } else {

            throw new UsernameNotFoundException(ErrorKey.USER_NOT_FOUND.name());

        }


    }

    @Override
    public boolean supports(Class<?> authentication) {

        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}

如果我使用以下代码进行身份验证,那么它可以正常工作

package com.websopti.wotms.auth;

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 org.springframework.stereotype.Service;

import com.websopti.wotms.entity.User;
import com.websopti.wotms.enums.ErrorKey;
import com.websopti.wotms.service.UserService;

@Service
public class AuthenticationService implements UserDetailsService {

    @Autowired
    public UserService userService;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

        User user = userService.findByEmail(email);

        if(user != null)
            return user;
        else
            throw new UsernameNotFoundException(ErrorKey.USER_NOT_FOUND.name());
    }

}

有人可以指导我代码中存在什么问题吗?

最佳答案

根据doc

Note that both implemementations require a UserDetailsService. If you are using an authentication provider which doesn't use a UserDetailsService (for example, the LDAP provider) then it won't work unless you also have a UserDetailsService bean in your application context.

默认的 Remember-me 使用示例 TokenBasedRememberMeServices processAutoLoginCookie() 方法从 cookie 中检索 userDetails 以验证用户/密码详细信息。所以你需要一个自定义的 userDetailsS​​ervice 检查 thisthis

更新:

基本上记住我功能有两件事

  1. 成功登录后,它会创建一个“remeber-me”浏览器cookie,其中包含基于用户名、密码的 token (如果需要,可以计算 token 并将其保存在数据库中,也可以动态计算用户、密码的哈希值) .
  2. 当用户尝试在没有任何 session 的情况下访问安全页面( session 因超时而过期)时,RememberMe 服务将尝试通过从 cookie 中检索用户详细信息来自动登录用户,并在需要时验证用户详细信息。

如果您没有返回 UserDetails 信息的 UserDetailsS​​ervice,那么您需要像 TokenBasedRememberMeServices 一样实现 RememberMeServices 并调整代码。

关于java - Spring security Remember me 和自定义身份验证提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32311925/

相关文章:

java - Spring JPA - 连接非持久字段

spring-mvc - Thymeleaf 和 Spring Boot 的下拉列表

java - JRuby、Warbler 和 Java 的 CLASSPATH

Spring Consul - 禁用单元测试

java - 在执行功能文件之前删除范围报告html文件的方法?

java - Maven、spring、tomcat7 : What do I need in pom. xml 部署正确?

java - 关于基于 java 的 Spring 配置 : How to use bean generated in one of my dependency in my project

java - 为什么我的建议/切入点根本不运行?

java - OpenAM JEE 策略代理 3.5 和 5.x

java - 通知构建显示标题和图像,但不显示内容