Spring Securityはログインできません、エラー:ID「null」にマップされたPasswordEncoderがありません



Spring Security Cant Log



エラーの詳細は次のとおりです。

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id 'null' at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:238) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:198) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$LazyPasswordEncoder.matches(WebSecurityConfigurerAdapter.java:593) ~[spring-security-config-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:86) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]

WebSecurityConfigurerAdapterクラスを継承するWebSecurityConfigクラスを作成した後、configure(AuthenticationManagerBuilder auth)メソッドで情報取得およびパスワード検証ルールの認証ソースを定義する必要があります。 (configure関数の名前は重要ではありません。正式な使用法はconfigureGlobal(...)のようです。@ EnableWebSecurityまたは@EnableGlobalMethodSecurity、または@EnableGlobalAuthenticationでアノテーションが付けられたこのクラスでAuthenticationManagerBuilderを構成することが重要です)。

最初に使用した認証情報のソースはメモリ取得です-inMemoryAuthentication、コードは次のとおりです

protected void configure(AuthenticationManagerBuilder auth) throws Exception { //inMemoryAuthentication is obtained from memory auth.inMemoryAuthentication().withUser('user1').password('123456').roles('USER') }

スプリングセキュリティに付属のログインページを使用します。ログインすると、ユーザー名とパスワードが正しく、リソースを開くことができないか、ログインページにとどまります。そして、コンソールが例外を報告したことがわかりました-ID「null」にマップされたPasswordEncoderがありません。

インターネット上のBaiduは、これはSpring security 5.0がさまざまな暗号化方式を追加し、パスワード形式も変更したためであることを発見しました。

公式ドキュメントを見てみましょう。以下は公式文書です。

-------------------------------------------------- -------------------------------------------------- ---------------

パスワードの一般的な形式は次のとおりです。

id

そのようなPasswordEncoderどのencodedPasswordを検索するために使用される識別子です使用する必要があり、PasswordEncoderは、選択したidの元のエンコードされたパスワードです。 {パスワードの先頭にある必要があり、}で始まりますそしてidで終わります。 idの場合見つかりません、id nullになります。たとえば、以下は、異なるprotected void configure(AuthenticationManagerBuilder auth) throws Exception { //inMemoryAuthentication is obtained from memory auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser('user1').password(new BCryptPasswordEncoder().encode('123456')).roles('USER') } を使用してエンコードされたパスワードのリストです。元のパスワードはすべて「password」です。

/ / Inject the implementation class of userDetailsService auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder())

-------------------------------------------------- -------------------------------------------------- ---------------

上記の段落は、SpringSecurityのパスワードの保存形式が「{id} ............」であることを意味します。前のIDは暗号化方式であり、IDはbcrypt、sha256などの後に暗号化されたパスワードを続けることができます。つまり、プログラムが渡されたパスワードを取得すると、最初に「{」と「}」に含まれるIDを見つけて、パスワードの暗号化方法を決定します。見つからない場合、IDはNullと見なされます。これが、プログラムがエラーを報告する理由です。ID「null」にマップされたPasswordEncoderがありません。公式文書の例は、さまざまな暗号化方法が同じパスワードに対して暗号化され、元のパスワードが「password」であるストレージフォームです。

プロジェクトが正常にログインできるようにするには、configureのコードを変更する必要があります。フロントエンドで渡されたパスワードをなんらかの方法で暗号化したいと思います。 Spring Securityの公式の推奨事項は、bcrypt暗号化を使用することです。したがって、パスワードを暗号化する方法は、configureメソッドで指定するだけです。

変更後は次のようになります。

|_+_|

inMemoryAuthentication()の後に、さらに「.passwordEncoder(new BCryptPasswordEncoder())」があります。これは、ログイン時にBCrypt暗号化を使用してユーザーパスワードを処理するのと同じです。以前の「.password( '123456')」は「.password」になりました。 (new BCryptPasswordEncoder()。encode( '123456')) '、これはメモリ内のパスワードの暗号化をエンコードするBcryptと同等です。比較は同じであり、パスワードが正しく、ログインが許可されていることを示しています。

メモリからのパスワードを使用している場合は、上記の変更を行った後、正常にログインできるはずです。

データベースに保存されているユーザー名とパスワードを使用している場合は、通常、BCryptエンコーディングを使用してユーザーのパスワードを暗号化し、ユーザーの登録時にデータベースに保存する必要があります。そして、configure()メソッドを変更し、「。passwordEncoder(new BCryptPasswordEncoder())」を追加して、ユーザーがbcryptを使用してパスワードを処理し、データベース内のパスワードと比較するようにします。次のように:

|_+_|