https://www.cnblogs.com/merryyou/p/9100260.html

前言

在使用Spring Security Oauth2登录和鉴权失败时,默认返回的异常信息如下

{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}

。它与我们自定义返回信息不一致,并且描述信息较少。那么如何自定义Spring Security Oauth2异常信息呢,下面我们简单实现以下。格式如下:


{
"error": "400",
"message": "坏的凭证",
"path": "/oauth/token",
"timestamp": "1527432468717"
}

自定义登录失败异常信息

新增CustomOauthException

  • 添加自定义异常类,指定json序列化方式
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
public CustomOauthException(String msg) {
super(msg);
}
}

新增CustomOauthExceptionSerializer

  • 添加CustomOauthException的序列化实现
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {
public CustomOauthExceptionSerializer() {
super(CustomOauthException.class);
} @Override
public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); gen.writeStartObject();
gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));
gen.writeStringField("message", value.getMessage());
// gen.writeStringField("message", "用户名或密码错误");
gen.writeStringField("path", request.getServletPath());
gen.writeStringField("timestamp", String.valueOf(new Date().getTime()));
if (value.getAdditionalInformation()!=null) {
for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {
String key = entry.getKey();
String add = entry.getValue();
gen.writeStringField(key, add);
}
}
gen.writeEndObject();
}
}

添加CustomWebResponseExceptionTranslator

  • 添加CustomWebResponseExceptionTranslator,登录发生异常时指定exceptionTranslator
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {
public CustomOauthExceptionSerializer() {
super(CustomOauthException.class);
} @Override
public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); gen.writeStartObject();
gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));
gen.writeStringField("message", value.getMessage());
// gen.writeStringField("message", "用户名或密码错误");
gen.writeStringField("path", request.getServletPath());
gen.writeStringField("timestamp", String.valueOf(new Date().getTime()));
if (value.getAdditionalInformation()!=null) {
for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {
String key = entry.getKey();
String add = entry.getValue();
gen.writeStringField(key, add);
}
}
gen.writeEndObject();
}
}

修改MerryyouAuthorizationServerConfig

  • 指定自定义customWebResponseExceptionTranslator
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
//扩展token返回结果
if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> enhancerList = new ArrayList();
enhancerList.add(jwtTokenEnhancer);
enhancerList.add(jwtAccessTokenConverter);
tokenEnhancerChain.setTokenEnhancers(enhancerList);
//jwt
endpoints.tokenEnhancer(tokenEnhancerChain)
.accessTokenConverter(jwtAccessTokenConverter);
}
endpoints.exceptionTranslator(customWebResponseExceptionTranslator);
}

自定义Token异常信息

添加AuthExceptionEntryPoint

  • 自定义AuthExceptionEntryPoint用于tokan校验失败返回信息
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {

    @Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException)
throws ServletException { Map map = new HashMap();
map.put("error", "401");
map.put("message", authException.getMessage());
map.put("path", request.getServletPath());
map.put("timestamp", String.valueOf(new Date().getTime()));
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), map);
} catch (Exception e) {
throw new ServletException();
}
}
}

添加CustomAccessDeniedHandler

  • 授权失败(forbidden)时返回信息
@Slf4j
@Component("customAccessDeniedHandler")
public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Autowired
private ObjectMapper objectMapper; @Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
Map map = new HashMap();
map.put("error", "400");
map.put("message", accessDeniedException.getMessage());
map.put("path", request.getServletPath());
map.put("timestamp", String.valueOf(new Date().getTime()));
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(objectMapper.writeValueAsString(map));
}
}

修改MerryyouResourceServerConfig

    @Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.authenticationEntryPoint(new AuthExceptionEntryPoint())
.accessDeniedHandler(CustomAccessDeniedHandler);
}

效果如下

登录异常

token异常

禁止访问

token失效

代码下载

【转载】Spring Security Oauth2 自定义 OAuth2 Exception的更多相关文章

  1. Spring Security Oauth2 自定义 OAuth2 Exception

    付出就要得到回报,这种想法是错的. 前言 在使用Spring Security Oauth2登录和鉴权失败时,默认返回的异常信息如下 { "error": "unauth ...

  2. 朱晔和你聊Spring系列S1E10:强大且复杂的Spring Security(含OAuth2三角色+三模式完整例子)

    Spring Security功能多,组件抽象程度高,配置方式多样,导致了Spring Security强大且复杂的特性.Spring Security的学习成本几乎是Spring家族中最高的,Spr ...

  3. spring security使用自定义登录界面后,不能返回到之前的请求界面的问题

    昨天因为集成spring security oauth2,所以对之前spring security的配置进行了一些修改,然后就导致登录后不能正确跳转回被拦截的页面,而是返回到localhost根目录. ...

  4. spring security采用自定义登录页和退出功能

    更新... 首先采用的是XML配置方式,请先查看  初识Spring security-添加security 在之前的示例中进行代码修改 项目结构如下: 一.修改spring-security.xml ...

  5. [转载]spring security 的 logout 功能

    原文地址:security 的 logout 功能">spring security 的 logout 功能作者:sumnny 转载自:http://lengyun3566.iteye ...

  6. spring security 3 自定义认证,授权示例

    1,建一个web project,并导入所有需要的lib. 2,配置web.xml,使用Spring的机制装载: <?xml version="1.0" encoding=& ...

  7. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_06-SpringSecurityOauth2研究-Oauth2授权码模式-申请令牌

    3.3 Oauth2授权码模式 3.3.1 Oauth2授权模式 Oauth2有以下授权模式: 授权码模式(Authorization Code) 隐式授权模式(Implicit) 密码模式(Reso ...

  8. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_07-SpringSecurityOauth2研究-Oauth2授权码模式-资源服务授权测试

    下面要完成  5.6两个步骤 3.3.4 资源服务授权 3.3.4.1 资源服务授权流程 资源服务拥有要访问的受保护资源,客户端携带令牌访问资源服务,如果令牌合法则可成功访问资源服务中的资 源,如下图 ...

  9. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_09-SpringSecurityOauth2研究-Oauth2密码模式授权

    密码模式(Resource Owner Password Credentials)与授权码模式的区别是申请令牌不再使用授权码,而是直接 通过用户名和密码即可申请令牌. 测试如下: Post请求:htt ...

  10. spring security 之自定义表单登录源码跟踪

    ​ 上一节我们跟踪了security的默认登录页的源码,可以参考这里:https://www.cnblogs.com/process-h/p/15522267.html 这节我们来看看如何自定义单表认 ...

随机推荐

  1. 直播预告 | YashanDB 2023年度发布会正式定档11月8日,邀您共同见证国产数据库发展实践!

    11月8日,YashanDB 2023年度发布会将于云端直播开启,发布会以 「惟实·励新」 为主题,邀请企业用户.合作伙伴.广大开发者共同见证全新产品与解决方案.届时发布会将在墨天轮社区同步进行,欢迎 ...

  2. 精彩回顾|【2023 ACDU 中国行·深圳站】数据库主题交流活动成功举办!

    6月30日下午,[ACDU 中国行·深圳站]在深圳回酒店圆满落下帷幕.本次活动由中国数据库联盟(ACDU)联合墨天轮社区主办,围绕「数据库前沿技术揭秘及应用」这一主题,七位数据库行业的领军人物从数据库 ...

  3. 使用threejs创建一个长方体

    // 创建设备 正方体 // x1 X轴坐标 y1 Y轴坐标 item 设备的信息 可以把 item 嵌入到正方体里面 h : 高度 private initQuare1(x1:any,y1:any, ...

  4. Docker升阶

    一.Docker镜像 镜像的定义:镜像是一种轻量级.可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码.运行时需要的库以及环境变量和 ...

  5. Nuxt.js 应用中的 app:resolve 事件钩子详解

    title: Nuxt.js 应用中的 app:resolve 事件钩子详解 date: 2024/10/17 updated: 2024/10/17 author: cmdragon excerpt ...

  6. uni-app 监听返回按钮

    前置条件: 开发环境:windows 开发框架:uni-app , H5+,nativeJS 编辑器:HbuilderX 2.8.13 4. 兼容版本:安卓,IOS已作测试 进入正题: 文档地址uni ...

  7. ASP.Net Core使用Jenkins配合pm2自动化部署项目

    一.  新建一个自由风格的软件项目 二. General配置(参数化构建) 1. 用来选择部署的服务器(我这里只添加了一个,如果需要添加多个,一行一个就可以了) 2. 选择不同的环境变量 三.源码管理 ...

  8. Docker 自定义镜像Dockerfile使用详细教程

    认识 Dockerfile 文件 Dockerfile 用于构建 Docker 镜像,Dockerfile 文件是由一行行命令语句 组成,基于这些命令即可以构建一个镜像 比如下面就是一个Dockefi ...

  9. pjsip编译、说明及vs2022使用示例

    环境: window10_x64 & vs2022 pjsip版本: 2.14.1   之前整理过pjsip 2.10的编译及python使用示例: https://www.cnblogs.c ...

  10. Metal 开发教程(二)

    https://developer.apple.com/documentation/quartzcore/cametallayer?language=objc#3385893 CAMetalLayer ...