问题
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:
How I can use the Merchant object but Spring accepts Object UserDetails. How I can implement this functionality?
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