自定义登录表单。配置Spring安全性以获取JSON响应
我有一个简单的应用程序,分为两个部分:
- 后端通过Spring-boot / Spring-security公开REST服务
- 一个仅包含静态文件的前端。
Nginx服务器接收请求,该服务器监听端口80。
- 如果请求URL以/ api /开头,则该请求将重定向到后端。
- 否则,该请求由提供静态文件的nginx处理。
我创建了一个自定义登录表单(在前端部分),并且试图配置Spring-boot服务器。
在很多示例中,我可以看到如何定义“登录成功” URL和“登录错误” URL,但是我不希望Spring-security重定向用户。如果登录成功或HTTP
40x登录失败,我希望Spring-security用HTTP 200回答。
换句话说:我希望后端仅使用JSON回答,而不是HTML。
到目前为止,当我提交登录表单时,请求将被重定向,并获得默认的Spring登录表单作为答案。
我尝试使用.formLogin().loginProcessingUrl("/login");代替loginPage(""):
@Configuration@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("ADMIN");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login");
回答:
感谢M. Deinum和本指南,我找到了解决方案。
首先,登录表单本身存在配置问题。由于后端将context-
path设置为/api,所以自定义表单应该已经向提交了表单参数,/api/login但是实际上我正在向提交数据/api/login/(请注意/最后的内容)。
结果,我在不知不觉中试图访问受保护的资源!因此,该请求由默认AuthenticationEntryPoint值处理,默认行为是将用户重定向到登录页面。
作为解决方案,我实现了一个自定义AuthenticationEntryPoint:
private AuthenticationEntryPoint authenticationEntryPoint() { return new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.getWriter().append("Not authenticated");
httpServletResponse.setStatus(401);
}
};
}
然后在配置中使用它:
http .exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint())
我对其他处理程序也做了同样的事情:
@Configuration@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("ADMIN");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(successHandler())
.failureHandler(failureHandler())
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler())
.authenticationEntryPoint(authenticationEntryPoint())
.and()
.csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
;
}
private AuthenticationSuccessHandler successHandler() {
return new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.getWriter().append("OK");
httpServletResponse.setStatus(200);
}
};
}
private AuthenticationFailureHandler failureHandler() {
return new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.getWriter().append("Authentication failure");
httpServletResponse.setStatus(401);
}
};
}
private AccessDeniedHandler accessDeniedHandler() {
return new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.getWriter().append("Access denied");
httpServletResponse.setStatus(403);
}
};
}
private AuthenticationEntryPoint authenticationEntryPoint() {
return new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.getWriter().append("Not authenticated");
httpServletResponse.setStatus(401);
}
};
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
以上是 自定义登录表单。配置Spring安全性以获取JSON响应 的全部内容, 来源链接: utcz.com/qa/397275.html

