我有一个Spring-Boot REST控制器,受Spring-Security保护。它工作正常。如果客户端发送 HTTP 请求时没有在 HTTP 标头上具有正确的访问令牌,则如我所料,他会得到一个 HTTP 403 响应。
curl-i本地主机:8301/user/11:
HTTP/1.1 403
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 07 Nov 2019 16:25:45 GMT
{
"timestamp" : 1573143945072,
"status" : 403,
"error" : "Forbidden",
"message" : "Access Denied",
"path" : "/user/11"
}
我还有一个自定义错误处理程序,它处理REST方法中出现的所有错误:
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
...
return new ResponseEntity<>(json, httpStatus);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return new ResponseEntity<>(json, httpStatus);
}
}
现在,我想做的是在HTTP 403的情况下自定义错误响应,我想向客户端发送一个自定义JSON响应(与我在<code>ControllerExceptionHandler<code>中发送的JSON相同)。
不幸的是,上面的错误处理程序不处理HTTP 403,因为请求在到达我的REST方法之前被Spring-Security阻止了。
似乎我需要为Spring Security添加一些额外的代码,但我不确定。
你能把我引到正确的方向吗?
尝试覆盖您的http.execptionalHandling()。WebSecurityConfigureAdapter中的authenticationEntryPoint()具有如下自定义身份验证入口点类。
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger log =
LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
log.error("Responding for UnAuthorized request{} ", authException.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}
你试过吗?
@ExceptionHandler({Exception.class})
public ResponseEntity<Message> handleException(HttpServletRequest httpServletRequest, Throwable ex) {
Spring Boot使用BasicErrorController作为全局错误处理程序。即@ExceptionHander方法未处理的异常。要覆盖此默认行为,您需要实现ErrorController接口,如下所示。
CustomErrorController.java
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(path = "/error", produces = MediaType.APPLICATION_JSON_VALUE)
public class CustomErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "/errror";
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<Map<String, Object>>(status);
}
Map<String, Object> body = new HashMap<String, Object>();
body.put("timestamp", new Date());
body.put("status", HttpStatus.FORBIDDEN.value());
body.put("error", "Forbidden");
body.put("message", "My Custom Error Message");
return new ResponseEntity<>(body, status);
}
protected HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception ex) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}
请注意,使用这种方法,您将覆盖其他@ExceptionHandler方法未处理的所有异常(不仅仅是AccessDeniedException)的响应。
如果您不想这样做,并且只想覆盖AccessDeniedException的响应,那么您需要实现AccessDeniedHandler接口,如下所示,并将其添加到spring security的http配置中。
CustomAccessDeniedHandler.java
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.gson.Gson;
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
Map<String, Object> body = new HashMap<String, Object>();
body.put("timestamp", new Date());
body.put("status", HttpStatus.FORBIDDEN.value());
body.put("error", "Forbidden");
body.put("message", "Custom Error Message from CustomAccessDeniedHandler");
response.setStatus(HttpStatus.FORBIDDEN.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
new Gson().toJson(body, new TypeReference<Map<String, Object>>() {
}.getType(), response.getWriter());
}
}
WebSecurityConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler()).and().httpBasic().and()
.authorizeRequests().antMatchers("/rest/**").hasAnyRole("ROLE_ADMIN").anyRequest().authenticated().and()
.formLogin().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("USER").and().withUser("admin")
.password("{noop}password").roles("USER", "ADMIN");
}
我对大摇大摆的文档很陌生。我们有一个现有的项目正在为RESTFul Web服务开发进度语言。不同的基于资源的URL以Application/JSON格式使用和生成。下面给出了一个资源url的输入和输出json格式: 如何将上述请求和响应json格式转换为swagger 2.0 json格式? 谢了!
问题内容: 建议和有时是必要的,即表示值(类 值类 )来覆盖,[和任选]的方法。这些方法返回的值取决于类及其超类的成员变量的全部或子集。为了实现它们正常,你必须了解理论的一点点 散列 和代数和集理论的一点点(不要太多,几乎一切都在explaind 的javadoc 这些方法和有效的Java形式乔希布洛赫。) 在大多数情况下,此方法的实现遵循一个模板,并且IDE(如Eclipse JDT)包括生成它
在我的应用程序中,我必须知道,从一个列表中有一个服务器地址,这些地址是向上的。我发现的解决方案是从Spring引导执行器调用健康endpoint,对它们每个。JSon reponse是: 在应用程序的其他部分,我使用Spring-Cloud中的Feign客户机,这些客户机使用注释定义,它工作得很好: 不幸的是,这种配置不允许重用同一个客户机来调用不同地址上的同一个endpoint。因此,我必须定义
问题内容: 我已经编写了REST API服务,该服务要求所有响应均为JSON。但是,当Go HTTP请求解析器遇到错误时,它将返回400作为纯文本响应,而无需调用我的处理程序。例: 请注意无效的授权标头。当然,400是正确的响应,但是当然是文本/纯文本。有什么方法可以配置Go http解析器以使用自定义错误响应媒体类型和主体? 问题答案: 你不能 您可以在net / http源中找到它,只有在请求
我有一个自定义文件,其中包含我所有图像的路径及其标签,我在一个数据框中加载使用: MyIndex有两列感兴趣的ImagePath和ClassName 接下来我做一些训练测试拆分和编码输出标签为: 我面临的问题是一次性加载的数据太大,无法放入当前的机器内存,因此我无法处理完整的数据集。 我曾尝试使用datagenerator,但不想遵循它遵循的目录约定,也无法消除增强部分。 问题是,是否有一种方法可
问题内容: 我正在使用Struts创建Web应用程序。当请求网址格式不正确时,我想发出如下错误的JSON响应 我已经在使用struts2-json插件来使用JSON序列化响应对象。我应该如何发送JSON错误响应。我可以想到下面的方法。 在操作类中使用错误响应对象,并显式设置所有名称必需的名称值对 然后,我可以只处理序列化在我的。 我是Struts的新手,想知道是否有确定的方法来做到这一点?也许可以