我比上次更深入地检查了该主题,发现您必须确定用户是否由您自己在控制器中进行身份验证。Row Winch (Spring Security dev) 在这里说:
Spring Security不了解您的应用程序的内部(即,如果您想根据用户是否登录来灵活设置登录页面)。要在请求登录页且用户登录时显示您的主页,请使用登录页(或其控制器)中的 ,并将用户重定向或转发到主页。SecurityContextHolder
因此,解决方案是确定用户请求是否是匿名的,如下所示。/auth/login
应用程序上下文安全.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>
添加到应用程序上下文.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;
}
}
}
定义字符串bean似乎是一个黑客,但我没有更好的方法来不硬编码url...(实际上,在我们的项目中,我们使用<util:constant>
,类包含静态的最终字符串字段。但它毕竟有效。defaultTargetUrl