没有使用数据库身份验证为id"null"映射PasswordEncoder

Jus*_*ode 3 java spring-security spring-boot

我成功构建了内存中的身份验证.但是当我用数据库构建它时会出现这个错误.

没有为id"null"映射PasswordEncoder

接下来是教程 - 初学者的Spring Boot教程,10 - 使用Spring Security的高级认证| 强大的Java

有课程

SpringSecurityConfiguration.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);
}

}
Run Code Online (Sandbox Code Playgroud)

AuthenticationEntryPoint.java

@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();
}
Run Code Online (Sandbox Code Playgroud)

}

MyUserDetailsS​​ervice .java

@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;
}
}
Run Code Online (Sandbox Code Playgroud)

UserRepository接口

public interface UserRepository extends JpaRepository<User, Long>{

@Query("FROM User WHERE userName =:username")
User findByUsername(@Param("username") String username);

}
Run Code Online (Sandbox Code Playgroud)

Role.java

@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
}
Run Code Online (Sandbox Code Playgroud)

User.java

@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}
Run Code Online (Sandbox Code Playgroud)

如果您有任何想法请告知.谢谢.

Jus*_*ode 8

我更改了MyUserDetailsS​​ervice类的添加passwordEncoder方法.

添加行

BCryptPasswordEncoder encoder = passwordEncoder();
Run Code Online (Sandbox Code Playgroud)

改变了线

//changed, user.getPassword() as encoder.encode(user.getPassword())
return new org.springframework.security.core.userdetails.User(--)
Run Code Online (Sandbox Code Playgroud)

MyUserDetailsS​​ervice.java

@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();
}
Run Code Online (Sandbox Code Playgroud)


Ken*_*nen 6

从 Spring Security 5.x 开始,如果您使用的不是内存(生产)数据库,Spring Security 会强制您使用密码编码器。

Spring Security 通过激活DelegatingPasswordEncoder寻找PasswordEncoderbean的 default 来强制执行此操作。通过添加 a BCryptPasswordEncoderDelegatingPasswordEncoder将返回该实例以加密密码。

@Bean
public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
Run Code Online (Sandbox Code Playgroud)

我不建议你这样做,但如果你真的想要,你可以通过添加{noop}到密码值来覆盖密码编码。这将通过激活NoOpPasswordEncoder而不是默认值DelegatingPasswordEncoder来处理密码,并将您的密码视为纯文本。

请注意,如果您将应用程序部署到生产环境,则不建议这样做!