1 Spring Boot 在有异常发生时或者请求了一个受保护的资源亦或者用户没有通过认证的时候,默认返回的 Json 数据结构如下 : (用 Postman 测试接口)
{
“timestamp”: “2019-06-21 16:28:59”,
“status”: 403,
“error”: “Forbidden”,
“message”: “Access Denied”,
“path”: “/home/icon”
}
当前接口响应头状态吗status为403,显然,根据公司开发规范,需要返回结构为
{“code”: 403,“message”: “请先登陆!”,“data”:null},同时,响应头状态码也应该为200,而不是403(状态码为403,则前端需要在error哪里才能获取到请求结果,显然前端处理后台响应结果不方便的)
2 编写 SecurityConfig 类,SecurityConfig继承WebSecurityConfigurerAdapter:
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private TokenFilter tokenFilter;
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// 基于token,所以不需要session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
.antMatchers("/","/token", "/*.html", "/favicon.ico", "/css/**", "/js/**", "/fonts/**", "/layui/**", "/img/**",
"/v2/api-docs/**", "/swagger-resources/**", "/webjars/**", "/pages/**", "/druid/**",
"/statics/**","/login/**","/landing/**","/.well-known/**","/noLogin/**")
.permitAll().anyRequest().authenticated();
http.formLogin().and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.headers().frameOptions().disable();
http.headers().cacheControl();
http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
备注:其中tokenFilter为自定义过滤器,指定使用的过滤器,TokenFilter继承OncePerRequestFilter。
3 编写SecurityHandlerConfig,并在内 编写AuthenticationEntryPoint的实现类,AuthenticationEntryPointImpl:
/**
spring security处理器
@author:lucas
*/
@Configuration
public class SecurityHandlerConfig {
/**
未登录,返回401
@return
*/
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return new AuthenticationEntryPointImpl();
}
}
class AuthenticationEntryPointImpl implements AuthenticationEntryPoint{
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException){
ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + "", "请先登录");
ResponseUtil.responseJson(response,request, HttpStatus.OK.value(), info);
}
}
public class ResponseInfo implements Serializable {
private static final long serialVersionUID = -4417715614021482064L;
private String code;
private String message;
public ResponseInfo(String code, String message) {
super();
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class ResponseUtil {
public static void responseJson(HttpServletResponse response, HttpServletRequest request, int status, Object data) {
try {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setContentType("application/json;charset=UTF-8");
response.setStatus(status);
response.setStatus(status);
response.getWriter().write(JSONObject.toJSONString(data));
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 如此这样,即可实现未登录响应自定义结构,并且响应头状态码为200: