我成功构建了内存中的身份验证。但是当我用数据库构建它时会出现这个错误。
没有为id“null”
映射PasswordEncoder
这是教程 - Spring Boot Tutorial for Beginners, 10 - Advanced Authentication using Spring Security | Mighty Java
有课程
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends
WebSecurityConfigurerAdapter{
@Autowired
private AuthenticationEntryPoint entryPoint;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic()
.authenticationEntryPoint(entryPoint);
}
}
@Configuration
public class AuthenticationEntryPoint extends BasicAuthenticationEntryPoint{
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm -" +getRealmName());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("Http Status 401 "+authException.getMessage());
}
@Override
public void afterPropertiesSet() throws Exception {
setRealmName("MightyJava");
super.afterPropertiesSet();
}
}
@Service
public class MyUserDetailsService implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("User Name "+username +"Not Found");
}
return new org.springframework.security.core.userdetails.User(user.getUserName(),user.getPassword(),getGrantedAuthorities(user));
}
private Collection<GrantedAuthority> getGrantedAuthorities(User user){
Collection<GrantedAuthority> grantedAuthority = new ArrayList<>();
if(user.getRole().getName().equals("admin")){
grantedAuthority.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
grantedAuthority.add(new SimpleGrantedAuthority("ROLE_USER"));
return grantedAuthority;
}
}
public interface UserRepository extends JpaRepository<User, Long>{
@Query("FROM User WHERE userName =:username")
User findByUsername(@Param("username") String username);
}
@Entity
public class Role extends AbstractPersistable<Long>{
private String name;
@OneToMany(targetEntity = User.class , mappedBy = "role" , fetch = FetchType.LAZY ,cascade = CascadeType.ALL)
private Set<User> users;
//getter and setter
}
@Entity
public class User extends AbstractPersistable<Long>{
//AbstractPersistable class ignore primary key and column annotation(@Column)
private String userId;
private String userName;
private String password;
@ManyToOne
@JoinColumn(name = "role_id")
private Role role;
@OneToMany(targetEntity = Address.class, mappedBy = "user",fetch= FetchType.LAZY ,cascade =CascadeType.ALL)
private Set<Address> address; //Instead of Set(Unordered collection and not allow duplicates) we can use list(ordered and allow duplicate values) as well
//getter and setter}
如果您有任何想法请告知。谢谢。
答案 0 :(得分:6)
我更改了添加passwordEncoder
方法的MyUserDetailsService类。
添加了行
BCryptPasswordEncoder encoder = passwordEncoder();
更改了行
//changed, user.getPassword() as encoder.encode(user.getPassword())
return new org.springframework.security.core.userdetails.User(--)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
BCryptPasswordEncoder encoder = passwordEncoder();
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("User Name "+username +"Not Found");
}
return new org.springframework.security.core.userdetails.User(user.getUserName(),encoder.encode(user.getPassword()),getGrantedAuthorities(user));
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
答案 1 :(得分:3)
从Spring Security 5.x开始,如果您使用的不是内存(生产)数据库,Spring Security会强制您使用密码编码器。
Spring Security通过激活查找DelegatingPasswordEncoder
bean的默认PasswordEncoder
来强制执行此操作。
通过添加BCryptPasswordEncoder
,DelegatingPasswordEncoder
将返回该实例以加密密码。
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
我不建议您这样做,但如果您真的想这样做,可以通过将
{noop}
添加到密码值来覆盖密码编码。 这将通过激活NoOpPasswordEncoder
而不是默认DelegatingPasswordEncoder
来处理密码,并将您的密码视为纯文字。
请注意,如果您将应用程序部署到生产环境,则不建议这样做!