thymeleaf-extras-springsecurityでURLへのアクセス権の有無によってリンクとラベルを切り替える


thymeleaf-extras-springsecurity を使うと Thymeleaf で Spring Security のオブジェクトにアクセスできるようになります。

thymeleaf-extras-springsecurity には、指定のURLにアクセス可能である場合に要素を出力する sec:authorize-url="url" という属性があり、結構便利に使えます。この属性はアクセス権がない場合の処理には使えないので「アクセス権の有無によってリンクとラベルを切り替えたい」みたいなニーズは、この属性だけでは実現できません(と思います)。それをスマートに書けないか考えてみました。

以下の例では /admin にアクセス権がある場合に <a> タグが出力され、アクセス権がない場合は何も出力されません。

1
<a th:href="@{/admin}" sec:authorize-url="/admin">Admin</a>

Spring Security の認可系の処理は #authorization オブジェクトでアクセスできます。sec:authorize-url="/admin" は、このオブジェクトを使って th:if="${#authorization.url('/admin')}" と記述するのと同義です。これを使って、以下の例ではアクセス権がない場合はラベルで表示しています。

1
2
<span sec:authorize-url="/admin"><a th:href="@{/admin}">Admin</a></span>
<span th:unless="${#authorization.url('/admin')}">Admin</span>

書き方が統一されてなくてキモいですね。あと th:unless は個人的にあまり使いたくないし、条件文を2つ書いているのも「もにょり」ます。

個人的には th:switch を使うのが可読性もあり、素直な感じがしていいかなぁと思います。

1
2
3
4
<th:block th:switch="${#authorization.url('/admin')}">
  <span th:case="true"><a th:href="@{/admin}">Admin</a></span>
  <span th:case="false">Admin</span>
</th:block>

もっとスマートな書き方があれば教えていただけると嬉しいです。