【问题标题】:java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" [duplicate]java.lang.IllegalArgumentException:没有为 id“null”映射 PasswordEncoder [重复]
【发布时间】:2021-06-02 17:02:45
【问题描述】:

我是 Spring Security 的新手,并尝试在我的项目中使用 Spring Security,但此错误不断出现

这是我的道课

package com.voicechat.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.voicechat.entities.Credentials;
import com.voicechat.entities.Robi_nav;

public interface Robi_Dao_logIn extends JpaRepository<Credentials, Integer> {

    @Query("select c from Credentials c where c.uname = :uname")
    public Credentials getbyUname(@Param("uname") String uname);

}

这是我的凭证类

package com.voicechat.entities;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "credentials")
public class Credentials {

    @GeneratedValue
    @Id
    private int Id;
    private String uname;
    private String password;
    private String role;
    public int getId() {
        return Id;
    }
    public void setId(int id) {
        Id = id;
    }
    public String getUname() {
        return uname;
    }
    public void setUname(String uname) {
        this.uname = uname;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
    
    
    
    
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        role = role;
    }
    
    
    public Credentials(int id, String uname, String password, String role) {
        super();
        Id = id;
        this.uname = uname;
        this.password = password;
        role = role;
    }
    public Credentials() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Credentials [Id=" + Id + ", uname=" + uname + ", password=" + password + ", role=" + role + "]";
    }
}

我认为错误存在于这段代码中

package com.voicechat.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class MyConfig extends WebSecurityConfigurerAdapter {
    
    @Bean
    public UserDetailsService getUserDetailService() {

        return new UserDetailsServiceImpl();

    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();

    }

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

        auth.jdbcAuthentication().passwordEncoder(new BCryptPasswordEncoder());

    }

    @Bean
    public DaoAuthenticationProvider provider() {
        DaoAuthenticationProvider daoautpro = new DaoAuthenticationProvider();
        daoautpro.setUserDetailsService(this.getUserDetailService());
        return daoautpro;

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(provider());

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("//**").hasRole("ADMIN").and().formLogin().and().csrf().disable();

    }

}

这是用户详细信息

package com.voicechat.config;

import java.util.Collection;
import java.util.List;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.voicechat.entities.Credentials;

public class CustomUserDetails implements UserDetails {

    private Credentials cred;

    public CustomUserDetails(Credentials cred) {
        super();
        this.cred = cred;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        SimpleGrantedAuthority simple = new SimpleGrantedAuthority(cred.getRole());

        return List.of(simple);

    }

    @Override
    public String getPassword() {
        return cred.getPassword();
    }

    @Override
    public String getUsername() {

        return cred.getUname();
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return true;
    }

}

这是用户详细信息的实现

package com.voicechat.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.voicechat.dao.Robi_Dao_logIn;
import com.voicechat.entities.Credentials;



public class UserDetailsServiceImpl implements UserDetailsService{

    
    @Autowired
    private Robi_Dao_logIn login;
    
    
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        
        
        Credentials cred = (Credentials) login.getbyUname(username);
        System.out.println(" "+username);
        if (cred == null) {
            throw new UsernameNotFoundException("User Not Found");

        }
        CustomUserDetails custom=new CustomUserDetails(cred);

        return custom;
    }
    

}

这是弹出的错误

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:254) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:202) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:76) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:147) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-5.4.5.jar:5.4.5]
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:85) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:222) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.4.5.jar:5.4.5]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.4.jar:5.3.4]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.4.jar:5.3.4]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.4.jar:5.3.4]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.4.jar:5.3.4]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.43.jar:9.0.43]
    at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]

最后这是我的数据库,其中存储了 uname 和密码 arfe database table

这个错误让我发疯了我做了所有的事情来阻止这个但是这一次又一次弹出基本上我的项目是登录系统,其中一个uname和密码是手动存储的,并且uname和密码用于登录到Web服务

【问题讨论】:

  • 尝试将密码保存为passwordEncoder.encode(passwd) 可能对此有所帮助
  • 表示将用户的密码保存到数据库中。
  • stackoverflow.com/a/62770774/1840146之前有人问过这个问题

标签: java html spring-boot hibernate spring-security


【解决方案1】:

您已将密码定义为纯字符串,但随后您说要使用BCryptPasswordEncoder

如果你阅读官方的spring boot文档on password formats可以看到在数据库中存储密码时需要使用的格式是:

{id}encodedPassword

这意味着您需要在括号中定义解码密码时要使用的编码器的ID。

这里是一些示例密码,它们的编码器 ID 被定义在括号之间。

{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG 
{noop}password 
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc 
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=  
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0

这意味着在您的情况下,您的密码需要以以下格式存储:

{bcrypt}YourLongEncryptedPasswordAndNotPlainText.

您遇到的错误是因为 spring 获取您的用户,然后检查用户密码以查看其前缀,因此它可以使用相同的加密对传入的密码进行编码,然后与数据库中的密码进行匹配.但是当它查看定义的密码时,没有定义的编码器(没有定义编码器的括号),所以它抛出一个异常说它找不到。

最简单的解决方案是使用在线服务或在 Spring Boot 中使用 bcrypt 加密密码,然后将加密版本打印到控制台。获取该密码,确保它以{bcrypt} 开头并将其插入数据库。

【讨论】:

    【解决方案2】:

    从您的代码中,我可以看到您正在使用 Bcrypt 编码器。您是在告诉 Spring security 密码是使用它进行编码的(但实际上您并没有对其进行编码)。

     @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
    
        }
    

    在这种情况下,您需要在 loadUserByUsername 方法中使用 BCrypt 密码编码器对密码进行编码

    cred.setPassword(bCryptPasswordEncoder.encode(cred.getPassword()))
    

    还在同一类中自动装配 BCryptPasswordEncoder。

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder
    

    注意:最好在将密码保存到数据库时对其进行编码(使用 Bcrypt 编码器)。所以这在 loadUserByUsername 中不需要。

    【讨论】:

    • @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Credentials cred = (Credentials) login.getbyUname(username); cred.setPassword(bCryptPasswordEncoder.encode(cred.getPassword())); System.out.println(" " + 用户名); CustomUserDetails custom = new CustomUserDetails(cred);退货; } }
    • 按照您的建议使用后原因:java.lang.NullPointerException:无法调用“com.voicechat.entities.Credentials.getPassword()”,因为“cred”为空,此错误即将到来
    • 凭据 cred = (Credentials) login.getbyUname(username);在这里检查空指针。如果此 cred 为 null,则 cred.getPassword() 失败
    • 我的 quert 没有启动我不知道为什么
    • 包 com.voicechat.dao;导入 org.springframework.data.jpa.repository.JpaRepository;导入 org.springframework.data.jpa.repository.Query;导入 org.springframework.data.repository.query.Param;导入 com.voicechat.entities.Credentials;导入 com.voicechat.entities.Robi_nav; public interface Robi_Dao_logIn extends JpaRepository { @Query("select c from Credentials c where c.uname = :uname") public Credentials getbyUname(@Param("uname") String uname); }
    猜你喜欢
    • 2019-06-02
    • 2018-10-30
    • 2020-07-03
    • 2020-10-27
    • 2018-09-14
    • 2020-06-24
    • 2019-08-28
    • 2018-11-14
    相关资源
    最近更新 更多