gpt4 book ai didi

java - 自定义登录表单。配置 Spring 安全性以获取 JSON 响应

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:14:59 24 4
gpt4 key购买 nike

我有一个简单的应用程序,分为两部分:

  • 使用 Spring-boot/Spring-security 公开 REST 服务的后端
  • 仅包含静态文件的前端。

请求由监听端口 80 的 nginx 服务器接收。

  • 如果请求 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 并感谢 this guide ,我可以找到解决方案。

首先,登录表单本身存在配置问题。由于后端的上下文路径设置为 /api,自定义表单应该将表单参数提交给 /api/login 但我实际上是将数据提交给 /api/login/(注意末尾额外的 /)。

结果,我在不知不觉中试图访问 protected 资源!因此,请求由默认的 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;
}
}

关于java - 自定义登录表单。配置 Spring 安全性以获取 JSON 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32498868/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com