Custom Authentication Manager with Spring Security and Java Configuration

前端 未结 4 1292
渐次进展
渐次进展 2020-12-01 01:31

I am using Spring Security with SpringMVC to create a web application (I will refer to this as the WebApp for clarity) that speaks to an existing application (I will refer t

相关标签:
4条回答
  • 2020-12-01 01:58

    Take a look at my sample below. You have to return an UsernamePasswordAuthenticationToken. It contains the principal and the GrantedAuthorities. Hope I could help :)

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getPrincipal() + "";
        String password = authentication.getCredentials() + "";
    
        User user = userRepo.findOne(username);
        if (user == null) {
            throw new BadCredentialsException("1000");
        }
        if (!encoder.matches(password, user.getPassword())) {
            throw new BadCredentialsException("1000");
        }
        if (user.isDisabled()) {
            throw new DisabledException("1001");
        }
        List<Right> userRights = rightRepo.getUserRights(username);
        return new UsernamePasswordAuthenticationToken(username, null, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList()));
    }
    

    PS: userRepo and rightRepo are Spring-Data-JPA Repositories which access my custom User-DB

    SpringSecurity JavaConfig:

    @Configuration
    @EnableWebMvcSecurity
    public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    public MySecurityConfiguration() {
        super(false);
    }
    
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
    }
    
    }
    
    0 讨论(0)
  • 2020-12-01 01:59

    In its most simplest:

    @Override
        public Authentication authenticate(Authentication auth) throws AuthenticationException {
            String username = auth.getName();
            String password = auth.getCredentials().toString();
            // to add more logic
            List<GrantedAuthority> grantedAuths = new ArrayList<>();
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
        }
    
    0 讨论(0)
  • 2020-12-01 02:12

    First you must configure Spring security to use your custom AuthenticationProvider. So, in your spring-security.xml (or equivalent config file) you must define wich class is implementing this feature. For example:

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="myAuthenticationProvider" />
    </authentication-manager>
    
    <!-- Bean implementing AuthenticationProvider of Spring Security -->
    <beans:bean id="myAuthenticationProvider" class="com.teimas.MyAutenticationProvider">
    </beans:bean>
    

    Secondly you must implement AuthenticationProvider as in your example. Specially the method authenticate(Authentication authentication) in which your rest call must be. For example:

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        User user = null;
        try {
            //use a rest service to find the user. 
            //Spring security provides user login name in authentication.getPrincipal()
                user = userRestService.loadUserByUsername(authentication.getPrincipal().toString());
        } catch (Exception e) {
            log.error("Error loading user, not found: " + e.getMessage(), e);
        }
    
        if (user == null) {
            throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));
        } else if (!user.isEnabled()) {
            throw new UsernameNotFoundException(String.format("Not found enabled user for username ", user.getUsername()));
        }
        //check user password stored in authentication.getCredentials() against stored password hash
        if (StringUtils.isBlank(authentication.getCredentials().toString())
            || !passwordEncoder.isPasswordValid(user.getPasswordHash(), authentication.getCredentials().toString()) {
            throw new BadCredentialsException("Invalid credentials");
        }
    
        //doLogin makes whatever is necesary when login is made (put info in session, load other data etc..)
        return doLogin(user);
    } 
    
    0 讨论(0)
  • 2020-12-01 02:12

    My solution is almost the same as the first answer:

    1) You need a class which implements the Authentication Provider

    @Service
    @Configurable
    public class CustomAuthenticationProvider implements AuthenticationProvider    {
          @Override
          public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // Your code of custom Authentication
    }
    }
    

    2) Opposite to the first answer you don't need to have following code in your WebSecurityConfiguration if you have only this custom provider.

    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
         return new ProviderManager(Arrays.asList((AuthenticationProvider) new  AuthProvider()));
    }
    

    The issue is that Spring looks for available providers and use the default if nothing else is found. But as you have the implementation of the AuthenticationProvider - your implementation will be used.

    0 讨论(0)
提交回复
热议问题