key和sign的校验可以采用类似日志的切面方式(一个切点可以织入多种通知,例如即织入日志通知,又织入key校验通知)
切面基本思路是定义切点(截点),在切点(截点)处织入通知(前置通知,环绕通知,后置通知)
请求系统在业务数据之后加上key,sign,到达目标系统之后,目标系统用切面拦截(前置通知),校验key(和本地存的是否一致)和sign(加密方式,参数是否一致),通过之后remove掉key,sign留下业务数据(参数操作基于对象引用
,所以后传有效)自动从截点方法继续执行,不通过抛异常(环绕通知需要在通知处手动调用截点方法)
前置通知://不需要手动调用截点,自动运行
截点:
/**
* 所有controller
*/
@Pointcut("execution(* com.houbank.bank.*.controller..*.*(..))")
private void allController() {
}
通知
@Before(value = "allController()" +
"&&!callbackController()" +
"&&!taskController()" +
"&&!webController()" +
"&&!baseController()" +
"&&!nosignController()")
public void req(JoinPoint joinPoint) throws Throwable {
if(joinPoint.getArgs().length > 0){
Object jsonObject = (Object) joinPoint.getArgs()[0];
Map<String, Object> bodyMap = MapUtil.beansToMap(jsonObject);
String key = (String) bodyMap.get("key");
String sign = (String) bodyMap.get("sign");
if (StringUtils.isBlank(key) || StringUtils.isBlank(sign)) {
throw new ParamException("请检查参数key,sign");
}
String secret = null;
String[] split = appKey.split(";");
for (String str : split) {
if (str.split(",")[0].trim().equals(key)) {
secret = str.split(",")[1].trim();
if (logger.isDebugEnabled()) {
logger.debug("对方key=" + key + ",获取的秘钥secret=" + secret);
}
}
}
if (StringUtils.isBlank(secret)) {
logger.error("秘钥为空,对方key=" + key + ",我方appKey集合=" + appKey);
throw new ParamException("key不匹配");
} else {
bodyMap.remove("sign");
bodyMap.remove("key");
if (!SignUtils.signOuter(bodyMap, secret,sign)) {
throw new ParamException(CodeEnum.CODE_9998.getMsg());
}
}
}
}
环绕通知://环绕通知需要手动调用截点
/**
* 执行controller时调用
*/
@Pointcut("execution(* com.houbank.bank.*.controller..*.*(..))")
private void executeController() {
}
@Around("executeController()")
public Object notifyCreditAccountStatusFail(ProceedingJoinPoint joinPoint) throws Throwable {
if(joinPoint.getArgs().length > 0){
Object jsonObject = (Object) joinPoint.getArgs()[0];
Map<String, Object> map = MapUtil.beansToMap(jsonObject);
String applyNo = null;
if (!map.isEmpty()) {
applyNo = (String) map.get("applyNo");
MDC.put(ApiLogConst.REQUESTIP, request.getServerName());
MDC.put(ApiLogConst.REQUESTPORT, String.valueOf(request.getServerPort()));
MDC.put(ApiLogConst.REQUESTURI, request.getRequestURI());
MDC.put(ApiLogConst.REQUESTTYPE, request.getMethod());
MDC.put(ApiLogConst.APPLYNO, applyNo);
}
LogFactory.setTxId(String.format("applyNo:%s",applyNo));
}
try {
Object obj = super.logMethodArgsReturn(joinPoint); //环绕通知需要手动调用截点
return obj;
} finally {
MDC.remove(ApiLogConst.REQUESTIP);
MDC.remove(ApiLogConst.REQUESTPORT);
MDC.remove(ApiLogConst.REQUESTURI);
MDC.remove(ApiLogConst.REQUESTTYPE);
MDC.remove(ApiLogConst.APPLYNO);
LogFactory.destory();
}
}
发起方:
@Test
public void updateStatus() throws Exception {
String url="http://localhost:8080/bank-gateway/approval/update";
JSONObject jsonObj = new JSONObject();
jsonObj.put("id", "1");
jsonObj.put("status", "0");
Map map=JSONObject.parseObject(jsonObj.toJSONString());
jsonObj.put("key", "bankApi"); //相当于盐值
jsonObj.put("sign",SignUtils.signOuter(map,"a6e237fc-5a53-4e29-a961-813de44a9929")); //相当于加密密码
String resultStr = HttpClientUtil.httpJsonPost(url, jsonObj.toString());
System.out.println(resultStr);
}
接收方:(用上面的前置通知对比key,sign)
/**
* 更新
* @param
* @return
*/
@RequestMapping("update")
public ApiResponse update(@Valid @RequestBody ApprovalRule appRule, Errors errors) throws Exception {
try {
if (approvalRuleMapper.updateByPrimaryKeySelective(appRule)<1){
LOGGER.error(CodeEnum.CODE_9997.getMsg()+"参数:"+appRule.toString());
return ApiResponse.error(CodeEnum.CODE_0001);
}
return ApiResponse.error(CodeEnum.CODE_0000);
} catch (Exception e) {
LOGGER.error("更新rule异常,参数:"+appRule.toString());
return ApiResponse.error(CodeEnum.CODE_9999);
}
}
相关推荐
这不仅提升了用户体验,同时也加强了系统的安全性,因为用户的认证信息被安全地存储在USB Key中,而非易受攻击的服务器或本地计算机上。 ### 2. 描述中的数据库访问 在描述中提到了“有数据库的访问”,这意味着...
单点登录(Single Sign-On,简称SSO)是一种身份验证机制,允许用户在一个系统或服务中登录后,无需重新输入凭证即可访问其他相互信任的系统。在ASP.NET中实现SSO,通常需要解决跨站点的身份验证和状态同步问题。...
在Android应用开发中,为了发布应用到不同的分发平台,如360手机助手、百度手机助手等,通常需要创建多个渠道包,每个渠道对应一个特定的推广标识。"Android-Android多渠道打包V2签名自动化脚本"是解决这个问题的一...
在安装程序中,确保勾选 "Add Python X.X to PATH" 选项,这将自动将Python添加到系统环境变量中,方便在命令行中使用Python。 完成安装后,你可以在命令提示符或PowerShell中输入 python3 来启动Python解释器。
360加固是常见的安卓应用保护措施,旨在防止恶意攻击和逆向工程。而V2签名是Android系统中的一种高级签名方式,它提供了更强的安全性,确保应用的完整性和来源可信。Walle是一款流行的安卓渠道打包工具,它能够帮助...
2. `sign_cert.sh`: 可能用于使用自签发CA(如`openssl x509 -req -days <valid_days> -in cert.csr -signkey privkey.key -out cert.crt`)为证书签名。 3. `install_cert.sh`: 安装生成的证书到系统信任存储,以便...
### 基于Red Hat Enterprise Linux 5 Update 2 搭建SSL安全网站认证服务器(CA) #### 实验背景与目的 随着互联网技术的发展,数据传输的安全性变得尤为重要。SSL(Secure Sockets Layer)证书作为保障网络安全...
讨论如何正确处理URL参数中的特殊字符,避免潜在的错误和安全风险。 **5.5 如何在模板中实现缓存数据?** 讲解如何在模板中利用缓存技术,减少服务器负担,加快响应速度。 **5.6 JS脚本的常见问题** 列举并解决...
通过使用“安卓一键rom签名工具”,用户可以省去手动签名的复杂过程,快速完成对Android ROM的签名,从而更便捷地进行系统定制和调试工作。不过,理解签名背后的原理和流程对于解决可能出现的问题至关重要。
单点登录(Single Sign-On, SSO)是一种让用户只需登录一次就可以访问多个应用的机制。 1. 实现SSO功能,提升应用的安全性和便利性。 ##### 5.2 附件预览与上传 在移动应用中处理附件是一个常见的需求。 1. 实现...
此外,为了保护私钥的安全,通常会将密钥库文件存储在一个安全的位置,并在脚本中提供相应的访问路径。 总的来说,通过shell脚本自动化Android APK的重签名过程,我们能够高效地处理多个APK,同时保持签名的正确性...
生成证书是网络安全中的一项关键任务,主要用于验证服务器或客户端的身份。下面我们将详细介绍如何使用OpenSSL来生成证书,以及相关的证书转换操作。 一、OpenSSL编译与安装 在Windows环境下编译OpenSSL通常需要...
- 跨站脚本(XSS):攻击者可能注入恶意脚本获取或篡改JWT。 - 客户端会话有用吗? 客户端会话的无状态特性使得它在某些场景下非常有用,比如微服务架构。 - 联合身份和OAuth2: JWT可以与OAuth2和OpenID ...
在Android应用开发中,APK文件是应用程序的可分发格式,它包含了所有必要的资源、代码和元数据。...通过掌握apktool和Auto-Sign的使用,开发者可以更加便捷地对APK进行调试、定制和发布,确保应用的安全性和更新能力。
使用GPG可以确保数据的安全传输和验证发送者的身份。 - **安装**:通过`yum install gnupg`安装。 - **生成密钥**:`gpg --gen-key`生成一对公钥和私钥。 - **签名文件**:`gpg --sign 文件`对文件进行数字签名。 - ...
在IT行业中,尤其是在网络安全和Web开发领域,OpenSSL是一个至关重要的工具。OpenSSL是一个开源的库,包含了多种加密算法、安全协议以及相关的实用程序。它主要用于实现SSL/TLS协议,这些协议是确保网络通信安全的...
例如,通过加密、设置HttpOnly属性等手段,可以防止跨站脚本攻击(XSS)和其他安全威胁。与session相比,如果采取了安全措施,cookie的安全性可以与session持平。 #### 分布式服务部署的实现 使用cookie机制可以轻松...
其中,单点登录(Single Sign-On,SSO)与反向登录功能尤其受到重视,它们简化了用户在不同系统间切换时的认证过程,提升了用户体验,同时也加强了系统安全性。本文将深入探讨RTX与OA系统单点登录的实现原理与具体...
在Linux系统中,签名工具主要用于验证软件包的完整性和来源,确保它们没有被篡改或包含恶意代码。这些工具通常使用公钥加密算法,如RSA、DSA或ECDSA,来生成数字签名。数字签名可以看作是软件发布者对软件的一种电子...