在权限服务中,异常类不需要引入;
1. 权限不足
package cc.vace.cloud.custom;
import cc.vace.cloud.constant.RpsBody;
import cc.vace.cloud.constant.VcResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 权限不足异常类重写
*
* @author king
*/
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
e.printStackTrace();
//自定义返回格式内容
RpsBody rpsBody = new RpsBody();
rpsBody.setCode("1013");
rpsBody.setMessage("权限访问失败");
rpsBody.setData("");
response.setStatus(HttpStatus.OK.value());
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
printWriter.append(new ObjectMapper().writeValueAsString(VcResponse.save(rpsBody)));
}
}
2. token效验
package cc.vace.cloud.custom;
import cc.vace.cloud.constant.RpsBody;
import cc.vace.cloud.constant.VcResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author king
*/
@Component
public class CustomAuthenticationEntryPoint extends OAuth2AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
Throwable cause = e.getCause();
//自定义返回格式内容
RpsBody rpsBody = new RpsBody();
if (cause instanceof OAuth2AccessDeniedException) {
rpsBody.setCode("1001");
rpsBody.setMessage("资源ID不在resource_ids范围内");
} else if (cause instanceof InvalidTokenException) {
rpsBody.setCode("1002");
rpsBody.setMessage("Token解析失败");
}else if (e instanceof InsufficientAuthenticationException) {
rpsBody.setCode("1003");
rpsBody.setMessage("未携带token");
}else if (e instanceof BadCredentialsException) {
rpsBody.setCode("1004");
rpsBody.setMessage("客户端异常");
} else if (cause instanceof InvalidTokenException) {
rpsBody.setCode("1011");
rpsBody.setMessage("未登陆或token失效");
} else if (cause instanceof InvalidTokenException) {
rpsBody.setCode("1011");
rpsBody.setMessage("未登陆或token失效");
} else {
rpsBody.setCode("1012");
rpsBody.setMessage("该资源没有访问权限");
}
rpsBody.setData("");
response.setStatus(HttpStatus.OK.value());
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
printWriter.append(new ObjectMapper().writeValueAsString(VcResponse.save(rpsBody)));
}
}
3. client账号密码错误异常处理
package cc.vace.cloud.custom;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author king
*/
public class CustomClientCredentialsTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter {
private AuthorizationServerSecurityConfigurer configurer;
private AuthenticationEntryPoint authenticationEntryPoint;
public CustomClientCredentialsTokenEndpointFilter(AuthorizationServerSecurityConfigurer configurer) {
this.configurer = configurer;
}
@Override
public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
// 重载方法
super.setAuthenticationEntryPoint(null);
this.authenticationEntryPoint = authenticationEntryPoint;
}
@Override
protected AuthenticationManager getAuthenticationManager() {
return configurer.and().getSharedObject(AuthenticationManager.class);
}
@Override
public void afterPropertiesSet() {
/*效验失败*/
setAuthenticationFailureHandler(
new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
authenticationEntryPoint.commence(httpServletRequest, httpServletResponse, e);
}
}
// (httpServletRequest, httpServletResponse, e) -> authenticationEntryPoint.commence(httpServletRequest, httpServletResponse, e)
);
/*效验成功*/
setAuthenticationSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> {});
}
}
登录失败
package cc.vace.cloud.translator;
import cc.vace.cloud.constant.RpsBody;
import cc.vace.cloud.constant.VcResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.*;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
/**
* 登录失败异常处理
* @author king
*/
public class ResponseExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception> {
private static final String TOKEN = "token";
private static final String AUTHORIZATION = "authorization";
@Override
public ResponseEntity translate(Exception e) {
e.printStackTrace();
RpsBody rpsBody = new RpsBody();
if (e instanceof InvalidGrantException) {
e.getMessage();
System.out.println(e.getMessage());
if (e.getMessage().indexOf(TOKEN) > 0) {
rpsBody.setMessage("token已失效");
} else if (e.getMessage().indexOf(AUTHORIZATION) > 0){
rpsBody.setMessage("无效的授权码");
} else {
rpsBody.setMessage("用户名或密码错误");
}
rpsBody.setCode("1006");
rpsBody.setData("");
}else if (e instanceof InvalidTokenException) {
rpsBody.setCode("1007");
rpsBody.setMessage("登录过期");
rpsBody.setData("");
} else if (e instanceof InvalidScopeException) {
rpsBody.setCode("1008");
rpsBody.setMessage("有效范围错误");
rpsBody.setData("");
}else if (e instanceof UnsupportedGrantTypeException) {
rpsBody.setCode("1009");
rpsBody.setMessage("验证类型错误");
rpsBody.setData("");
} else {
rpsBody.setCode("1010");
rpsBody.setMessage("登录失败,请重试");
rpsBody.setData("");
}
return new ResponseEntity(VcResponse.save(rpsBody), HttpStatus.OK);
}
}
在资源服务器需要在引入
在ResourceServerConfiguration中
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.tokenServices(tokenServices())
// 无效token异常类重写
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
// 权限不足异常类重写
.accessDeniedHandler(new CustomAccessDeniedHandler());
}