Java Spring security记住我和自定义身份验证提供程序

Java Spring security记住我和自定义身份验证提供程序,java,spring,spring-mvc,authentication,spring-security,Java,Spring,Spring Mvc,Authentication,Spring Security,春天的问题记得我吗 在我的spring安全应用程序中,我有一个自定义的身份验证提供程序,它可以验证并返回自定义的身份验证对象,身份验证工作得很好,但我对spring记住我的服务有一个问题,它不能正常工作 但是,当我通过正常的spring安全性进行身份验证时,通过使用UserDetailService,记住我可以完美地工作,我的代码如下 package com.websopti.wotms.auth; import java.io.IOException; import java.util.Ar

春天的问题记得我吗

在我的spring安全应用程序中,我有一个自定义的身份验证提供程序,它可以验证并返回自定义的身份验证对象,身份验证工作得很好,但我对spring记住我的服务有一个问题,它不能正常工作

但是,当我通过正常的spring安全性进行身份验证时,通过使用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);
    }

}
有人能告诉我代码中的问题是什么吗?

根据

请注意,这两种实现都需要UserDetailsService。如果你 使用的身份验证提供程序不使用 UserDetailsService(例如,LDAP提供程序)则无法工作 除非应用程序中还有UserDetailsService bean 上下文

示例默认记住我使用ProcessAutologyCookie()方法从cookie中检索userDetails以验证用户/密码详细信息。因此,您需要自定义UserDetails服务检查或

更新:

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

  • 成功登录后,它将创建一个“Rememmeber me”浏览器cookie,其中包含一个基于用户名、密码的令牌(如果需要,可以计算令牌并将其保存在db中,也可以动态计算用户、密码的哈希值)
  • 当用户尝试在没有任何会话的情况下访问受保护的页面(会话因超时而过期)时,Memberme服务将尝试通过从cookie中检索用户详细信息来自动登录用户,并可在需要时验证用户详细信息
    如果您没有返回UserDetails信息的UserDetails服务,那么您需要实现像tokenbasedrembermeservices这样的membermeservices,并调整代码

    我有同样的问题,添加了
    auth.userDetailsService(userService)修复它

    @Autowired
    私有身份验证服务用户详细信息服务;
    @自动连线
    私有CustomAuthenticationProvider;
    @自动连线
    public void configureGlobal(AuthenticationManagerBuilder auth)引发异常{
    //将验证过程交给自定义验证工具
    auth.userDetailsService(userService);
    身份验证提供者(提供者);
    }
    
    当您使用Spring自定义身份验证提供程序时,您需要创建自己的“记住我”服务,并将其配置到Spring安全配置文件中

    以下是供参考的链接:

    记住我和自定义身份验证提供程序的问题是:

  • 您已经在自定义身份验证提供程序中进行了身份验证
  • 之后,记得我在spring安全链中再次调用userdetails服务。此时,userdetail服务将身份验证主体作为输入参数,您无法从dbo获取任何用户详细信息,它将不会执行此筛选器
  • public UserDetails loadUserByUsername(字符串移动)抛出 UsernameNotFoundException{ System.out.println(移动);//在这里您可以 如果已经通过身份验证并且 不会获取任何用户死亡信息。}

    我不确定下面的解决方案是否正确,但它对我来说很好


    而不是返回UsernamePasswordAuthenticationToken对象返回身份验证对象。

    在我的应用程序中,我通过WebService对用户进行身份验证,因此我需要用户通过获取我正在验证的凭据输入用户名和密码,这样就不会使用UserDetailService,因为我从CustomeAuthenticationProvider。我已经检查了链接,但我使用的是springboot,没有太多的想法。
    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());
        }
    
    }
    
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
    
        Customer user = null;
    
        user = customerDataManager.findCustomerByMobile(auth.getName());
        if ((user == null)) {
            throw new BadCredentialsException("Invalid username or password");
        }
        final Authentication result = super.authenticate(auth);
    
        return result;
    }