不是开发API的专家,因此需要社区提供一些帮助/建议。 我有一个使用Java Spring MVC for API的应用程序。我正在使用ResponseEntity将响应返回给任何使用API(第三方或UI)的人。 我的API示例
@Controller
@RequestMapping("/Test/")
public ResponseEntity<TestGroup> getTestsById(@PathVariable("id") Integer id) {
TestGroup testGroup = testService.getTestById(id); //calls a service that returns test from the db
if(testGroup != null) {
return new ResponseEntity(testGroup, HttpStatus.OK);
} else {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
}
我有其他类似的API。我的问题是,是否有任何框架或方法,以便我可以让我的API返回JSON响应错误或成功的格式良好的JSON。实施例
{
"code": 400,
"message": "Bad Request",
"description": "There were no credentials found."
}
{
"code": 200,
"data": "{<JSON blob of the object to be returned>}"
}
另外, 在映射任何路由之前,已实施过滤器以检查会话信息(将其视为oauth tokes)以进行身份验证。我也需要这个错误处理过程在那个阶段工作,这样如果有一个过期的令牌或无效的令牌,我会得到一个格式良好的JSON。实施例
{
"code": 401,
"message": "Unauthorized",
"description": "The token used in the request is incorrect or has expired."
}
现在我收到默认消息Spring的身份验证过滤器以HTML的形式出现
<html><head><title>Apache Tomcat/7.0.50 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - Access is denied</h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u>Access is denied</u></p><p><b>description</b> <u>The server encountered an internal error that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>org.springframework.security.access.AccessDeniedException: Access is denied
org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
com.test.security.CookieAuthenticationFilter.doFilter(CookieAuthenticationFilter.java:95)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
</pre></p><p><b>note</b> <u>The full stack trace of the root cause is available in the Apache Tomcat/7.0.50 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.50</h3></body></html>
为不通信而道歉,我没有使用Spring的安全性,而我的web.xml过滤器看起来像这样
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Webapp</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.test.spring.config</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.test.spring.config=</param-value>
</init-param>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
以下是处理安全配置的方法。
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
@Autowired
private AbstractConfiguration configurationManager;
public SecurityConfiguration() {
super(true);
}
@Override
@Bean
protected AuthenticationManager authenticationManager() {
return new CustomAuthenticationManager();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/health/**").permitAll().and().authorizeRequests()
.antMatchers("/complete/**").permitAll().and()
.addFilterBefore(cookieAuthenticationFilter(), ChannelProcessingFilter.class).authorizeRequests()
.antMatchers("/**").hasAuthority("tests");
}
@Bean
public GenericFilterBean cookieAuthenticationFilter() {
if (System.getProperty("noauth") != null) {
return new SecurityFilterMock();
} else {
return new CookieAuthenticationFilter(redisTemplate());
}
}
}
根据建议,如果你在下面阅读,我已经做了以下EntryPoint类来处理令牌认证并显示一个JSON
public class TokenAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
private static final Logger log = LoggerFactory.getLogger(TokenAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest request,HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
log.info(String.format("Unauthorized access with session id '%s'",
request.getSession().getId()));
ErrorHandler errorResponse = new ErrorHandler();
// populate your response object with all the info you need
errorResponse.setCode(401);
errorResponse.setDescription("The token used in the request is incorrect or invalid.");
errorResponse.setMessage("Unauthorized");
ObjectMapper jsonMapper = new ObjectMapper();
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpStatus.UNAUTHORIZED.value());
PrintWriter out = response.getWriter();
out.print(jsonMapper.writeValueAsString(errorResponse));
}
}
任何建议或指示都会非常感激
答案 0 :(得分:2)
要将JSON格式的错误返回到使用Spring进行身份验证,您可以在此处查看我的答案:How to return JSON response for unauthorized AJAX calls instead of login page as AJAX response?
基本上,您必须调整身份验证机制并重新定义入口点以正确处理响应。