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

时间:2015-08-31 13:01:17

标签: java spring spring-mvc authentication spring-security

春天的问题记得我

在我的春季安全应用程序中,我有自定义身份验证提供程序验证并返回自定义身份验证对象,身份验证工作正常但我遇到问题春天记住我的服务它无法正常工作

但是当我通过正常的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);
    }

}

如果我使用以下代码进行身份验证,则可以正常使用

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

}

有人能指导我在我的代码中出现什么问题吗?

3 个答案:

答案 0 :(得分:0)

根据doc

  

请注意,这两个实现都需要UserDetailsS​​ervice。如果你   正在使用不使用a的身份验证提供程序   UserDetailsS​​ervice(例如,LDAP提供程序)然后它不会工作   除非您的应用程序中还有一个UserDetailsS​​ervice bean   上下文。

示例默认值remember-me使用TokenBasedRememberMeServices processAutoLoginCookie()方法从cookie中检索userDetails以验证用户/密码详细信息。因此,您需要自定义userDetailsS​​ervice检查thisthis

更新:

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

  1. 成功登录后,会创建一个&#34;记住我&#34;浏览器cookie,带有基于用户名,密码的令牌(如果需要,可以在db中计算并保存令牌,或者可以使用用户的密码计算哈希值)。
  2. 当用户尝试访问没有任何会话的安全页面(会话因超时而过期)时,RememberMe服务将尝试通过从cookie检索用户详细信息来自动登录用户,并在需要时验证用户详细信息。
  3. 如果您没有返回UserDetails信息的UserDetailsS​​ervice,那么您需要实现RememberMeServices,如TokenBasedRememberMeServices并调整代码。

答案 1 :(得分:0)

我遇到同样的问题,并添加auth.userDetailsService(userService);修复

  @Autowired
  private AuthenticationService userDetailsService;
  @Autowired
  private CustomAuthenticationProvider provider;
  @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        //将验证过程交给自定义验证工具
        auth.userDetailsService(userService);
        auth.authenticationProvider(provider);
    }

答案 2 :(得分:0)

当您使用Spring自定义身份验证提供程序时,您需要自己记住我的服务并将其配置为spring security配置文件。

以下是供参考的链接: https://samerabdelkafi.wordpress.com/2016/01/25/secure-angularjs-application-with-spring-security/

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

  1. 您已在自定义身份验证提供程序中进行了身份验证。
  2. 之后记得我再次在spring安全链中过滤调用userdetails服务。那时userdetail服务将身份验证主体作为输入参数,你不能从dbo获取任何用户详细信息,它将不会执行此过滤器。
  3.   

    public UserDetails loadUserByUsername(String mobile)throws   UsernameNotFoundException {   的System.out.println(移动); //你在这里   如果您已经过身份验证,则获取经过身份验证的主体用户对象   不会得到任何用户deatils。 }

    我不确定以下解决方案是否对,但对我来说效果很好。

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

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