Spring Securityではまったので、備忘録のために残しておく。
前提
Springの勉強として、「Spring徹底入門」のチュートリアルを進めていた。
本のバージョンは古いため、バージョンは最新版に変更することとした。
ただし、とりあえずコード自体はそのまま模写し、エラーになる部分だけ随時変更。
全体が動くようになってから、コードも最新版に合わせて変更するつもりでいた。
現象
Spring Securityを使ったログイン機能実装までは想定通りに動くことを確認(p.684)。
その後、Spring Securityの認証ユーザーを使った予約処理に変更後、途中からエラーで画面が進めなくなった。
・ログイン:可能(ログイン失敗の場合はエラーメッセージも出る)
・会議室一覧:表示される
・会議室の予約:エラー(500)
エラーメッセージの一部はこんな感じ。
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/reservation/reserveForm.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/reservation/reserveForm.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
〜省略〜
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#authentication.principal.user" (template: "reservation/reserveForm" - line 10, col 7)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 84 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authentication.principal.user" (template: "reservation/reserveForm" - line 10, col 7)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
〜省略〜
org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleOpenElementEnd(OutputExpressionInlinePreProcessorHandler.java:186)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:124)
at org.attoparser.HtmlElement.handleOpenElementEnd(HtmlElement.java:109)
〜省略〜
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'principal' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
原因
原因に対してのエラーメッセージはこの部分。
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'principal' cannot be found on null
このエラーメッセージの該当ソースはこちら。
<body th:with = "user=${#authentication.principal.user}">
エラーメッセージは、「#authentication」がわからないからnullだよって教えてくれているんだけど、
「principal」の中身がnullと勘違いしてて。。。(Google先生に訳してもらえばよかったw)
なんで値が入らないのかと色々と試してた笑
で、本題に戻りまして。
「#authentication」が認識できないということは、Spring Securityを認識していないのかなと気づく。
そこで、バージョンを確認。
エラー時のバージョン
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
</parent>
〜省略〜
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
spring-boot-2.2.5では、spring-security-coreは5.2.1なので、
thymeleaf-extras-springsecurity5を使わないといけないのに、
thymeleaf-extras-springsecurity4を指定していました。
(ここは最初のバージョン上げで意識せずに、本と同じものを指定していた)
結論
以下のように修正したことで、無事に動くようになりました!!
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>