前回よりも深くトピックを確認したところ、コントローラーでユーザーが自分で認証されているかどうかを判断する必要があることがわかりました。Row Winch (Spring Security dev)は次のように述べています。
Spring Security は、アプリケーションの内部を認識しません (つまり、ユーザーがログインしているかどうかに基づいてログイン ページを変更する場合)。ログイン ページが要求され、ユーザーがログインしているときにホームページを表示するにSecurityContextHolder
は、ログイン ページ (またはそのコントローラー) で を使用し、ユーザーをホームページにリダイレクトまたは転送します。
したがって、解決策は、ユーザーのリクエスト/auth/login
が匿名かどうかを判断することです。以下のようになります。
applicationContext-security.xml :
<http auto-config="true" use-expressions="true"
access-decision-manager-ref="accessDecisionManager">
<intercept-url pattern="/auth/login" access="permitAll" />
<intercept-url pattern="/auth/logout" access="permitAll" />
<intercept-url pattern="/admin/**" access="ADMINISTRATIVE_ACCESS" />
<intercept-url pattern="/**" access="XYZ_ACCESS" />
<form-login login-page="/auth/login"
authentication-failure-url="/auth/loginFailed"
authentication-success-handler-ref="authenticationSuccessHandler" />
<logout logout-url="/auth/logout" logout-success-url="/auth/login" />
</http>
<beans:bean id="defaultTargetUrl" class="java.lang.String">
<beans:constructor-arg value="/content" />
</beans:bean>
<beans:bean id="authenticationTrustResolver"
class="org.springframework.security.authentication.AuthenticationTrustResolverImpl" />
<beans:bean id="authenticationSuccessHandler"
class="com.example.spring.security.MyAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" ref="defaultTargetUrl" />
</beans:bean>
applicationContext.xml Bean 定義に追加します。
<bean id="securityContextAccessor"
class="com.example.spring.security.SecurityContextAccessorImpl" />
クラスです
public final class SecurityContextAccessorImpl
implements SecurityContextAccessor {
@Autowired
private AuthenticationTrustResolver authenticationTrustResolver;
@Override
public boolean isCurrentAuthenticationAnonymous() {
final Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
return authenticationTrustResolver.isAnonymous(authentication);
}
}
シンプルなインターフェースの実装
public interface SecurityContextAccessor {
boolean isCurrentAuthenticationAnonymous();
}
(SecurityContextHolder
コードへのアクセスはコントローラーから切り離されています。この回答からの提案に従いました。したがって、SecurityContextAccessor
インターフェイスです。)
最後になりましたが、コントローラのリダイレクト ロジック:
@Controller
@RequestMapping("/auth")
public class AuthController {
@Autowired
SecurityContextAccessor securityContextAccessor;
@Autowired
@Qualifier("defaultTargetUrl")
private String defaultTargetUrl;
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
if (securityContextAccessor.isCurrentAuthenticationAnonymous()) {
return "login";
} else {
return "redirect:" + defaultTargetUrl;
}
}
}
String Bean の定義defaultTargetUrl
はハックのように思えますが、URL をハードコーディングしないためのより良い方法はありません... (実際、私たちのプロジェクトでは、<util:constant>
静的な final String フィールドを含むクラスで使用しています)。