Configure Spring to use Database for authentication

末鹿安然 提交于 2019-12-24 18:32:05

问题


I want to configure Spring Security to use database for Rest api requests. I tried this:

    @Configuration
    @EnableWebSecurity
    @Import(value= {Application.class, ContextDatasource.class})
    @ComponentScan(basePackages= {"org.rest.api.server.*"})
    public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired 
        private RestAuthEntryPoint authenticationEntryPoint;

        @Autowired
        MyUserDetailsService myUserDetailsService;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    //      auth
    //      .inMemoryAuthentication()
    //      .withUser("test")
    //      .password(passwordEncoder().encode("testpwd"))
    //      .authorities("ROLE_USER");
            auth.userDetailsService(myUserDetailsService);
            auth.authenticationProvider(authenticationProvider());
        }
        @Bean
        public DaoAuthenticationProvider authenticationProvider() {
            DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
            authenticationProvider.setUserDetailsService(myUserDetailsService);
            authenticationProvider.setPasswordEncoder(passwordEncoder());
            return authenticationProvider;
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
            .authorizeRequests()
            .antMatchers("/securityNone")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint);
        }
        @Bean
        public PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
    }

Service:

    public interface MerchantsService {

        public Merchants getCredentials(String login, String pwd) throws Exception;
    }

Service implementation

@Service
@Qualifier("merchantsService")
@Transactional
public class MerchantsServiceImpl implements MerchantsService {

    @Autowired
    private EntityManager entityManager;

    @Override
    public Merchants getCredentials(String login, String pwd) throws Exception {
        String hql = "select e from " + Merchants.class.getName() + " e where e.login = ? and e.pwd = ?";

        Query query = entityManager.createQuery(hql).setParameter(0, login).setParameter(1, pwd);
        Merchants merchants = (Merchants) query.getSingleResult();

        return merchants;
    }
}



    @Service
    public class MyUserDetailsService implements UserDetailsService {

        @Autowired
        private MerchantsService merchantsService;

        @Override
        public Merchants loadUserByUsername(String username) {
            Merchants user = merchantsService.getCredentials(username, pwd);
            if (user == null) {
                throw new UsernameNotFoundException(username);
            }
            return user;
        }
    }

I have 2 issues:

  1. How I can use the Merchant object but Spring accepts Object UserDetails. How I can implement this functionality?

  2. How I can authenticate requests with username and password. I see that public UserDetails loadUserByUsername(String username) can accept only username. Is there other way to implement the code?


回答1:


You have to return User class object which is itself implementation of UserDetails interface. After getting authentication, you are getting Merchants object. You have to get the user credentials from it and also the role. One more suggestion, try to keep class name as singular.

public UserDetails loadUserByUsername(String username) {
 Merchants user = merchantsService.getCredentials(username, pwd);

        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        for (Role role : user.getRoles()){
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
}

You don't need to do password match your own, it does by Spring Security by their own using PasswordEncoder.

For more detail go through the below link. https://hellokoding.com/registration-and-login-example-with-spring-security-spring-boot-spring-data-jpa-hsql-jsp/




回答2:


When you use Spring Security you have to implement a service that implements the UserDetailsService and th corresponding loadUserByUsername method that returns UserDetails. Here is a sample method:

@Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = this.getUserByUsername(username); // getting the user from the database with our own method
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
  }

You dont have to worry about authenticating the password because spring security will tak of it.



来源:https://stackoverflow.com/questions/52225299/configure-spring-to-use-database-for-authentication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!