ada*_*shr 18 java spring-security
这是我的spring安全配置:
<http pattern="/auth/login" security="none" />
<http pattern="/auth/loginFailed" security="none" />
<http pattern="/resources/**" security="none" />
<http auto-config="true" access-decision-manager-ref="accessDecisionManager">
<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>
Run Code Online (Sandbox Code Playgroud)
这authenticationSuccessHandler扩展了SavedRequestAwareAuthenticationSuccessHandler确保用户被重定向到他最初请求的页面.
但是,由于/auth/login标记为security="none",如果用户在登录后访问登录页面,则无法成功将用户重定向到主页.我相信这也是正确的用户体验.
我也尝试了以下但是Principal对象总是null,大概是因为security="none"属性再次.
@RequestMapping(value = "/auth/login", method = GET)
public String showLoginForm(HttpServletRequest request, Principal principal) {
if(principal != null) {
return "redirect:/";
}
return "login";
}
Run Code Online (Sandbox Code Playgroud)
我比上次更深入地检查了这个主题,发现你必须确定用户是否在控制器中自己进行了身份验证.Row Winch(Spring Security dev)在这里说:
Spring Security不知道您的应用程序的内部(即,如果您希望根据用户是否登录而使您的登录页面变为flex).要在登录页面被请求并且用户已登录时显示您的主页,请使用
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>
Run Code Online (Sandbox Code Playgroud)
添加到applicationContext.xml bean定义:
<bean id="securityContextAccessor"
class="com.example.spring.security.SecurityContextAccessorImpl" />
Run Code Online (Sandbox Code Playgroud)
这是班级
public final class SecurityContextAccessorImpl
implements SecurityContextAccessor {
@Autowired
private AuthenticationTrustResolver authenticationTrustResolver;
@Override
public boolean isCurrentAuthenticationAnonymous() {
final Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
return authenticationTrustResolver.isAnonymous(authentication);
}
}
Run Code Online (Sandbox Code Playgroud)
实现简单的界面
public interface SecurityContextAccessor {
boolean isCurrentAuthenticationAnonymous();
}
Run Code Online (Sandbox Code Playgroud)
(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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
定义defaultTargetUrlString bean看起来像是一个hack,但我没有更好的方法来硬编码url ...(实际上在我们的项目中,我们使用<util:constant>包含静态最终String字段的类.)但它毕竟是有效的.
您还可以将登录页面限制为ROLE_ANONYMOUS并设置<access-denied-handler />:
<access-denied-handler ref="accessDeniedHandler" />
<intercept-url pattern="/auth/login" access="ROLE_ANONYMOUS" />
Run Code Online (Sandbox Code Playgroud)
并在您的处理程序中检查用户是否已经过身份验证:
@Service
public class AccessDeniedHandler extends AccessDeniedHandlerImpl {
private final String HOME_PAGE = "/index.html";
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && !(auth instanceof AnonymousAuthenticationToken)) {
response.sendRedirect(HOME_PAGE);
}
super.handle(request, response, e);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30359 次 |
| 最近记录: |