博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ApiAuthValue鉴权机制总结
阅读量:7060 次
发布时间:2019-06-28

本文共 10268 字,大约阅读时间需要 34 分钟。

一、背景介绍

1.自动化的配置工具autoconfig介绍

  项目开发过程中,有些配置会随着运行环境的变化而各不相同。如jdbc驱动的配置,在开发环境可能链接到开发本地的数据库,测试环境则有一套测试专用的数据库环境,如果一个应用要部署到多个idc中,那这些配置又有可能各不相同。如果每次上线时候人工的修改一下配置,比较容易出错,而且随着环境的增多成本会线性地增长。

  Autoconfig提供了一种动态替换配置信息的手段。并且Maven的强大插件机制,可以和autoconfig机制结合起来,发挥巨大的威力。pom.xml中配置autoconfig方法如下:

com.alibaba.citrus.tool
autoconfig-maven-plugin
1.2
true
autoconf/auto-config.xml
autoconf/conf/auto-config.xml
autoconf/conf/customize-autoconf/auto-config.xml
package
autoconfig
pom.xml

  Convention over Configuration(CoC),约定优于配置,上述配置文件中,充分体现了CoC原则。默认地插件会去扫描autoconf/auto-config.xml或者conf/META-INF/autoconf/auto-config.xml文件。autoconfig使用一套配置模板,为不同的环境生成相应的具体配置。它的核心思想是把一些可变的配置定义为一个模板,在autoconfig运行的时候从这些模板中生成具体的配置文件。

package test;import java.io.InputStream;import java.util.Properties;public class Testconfig {    /**     * 从classpath中读取配置文件component-beans.properties,然后输出到控制台     */    public static void main(String[] args) throws Exception {        InputStream is = Testconfig.class.getClassLoader().getResourceAsStream("component-beans.properties");        if (is == null) {            System.err.println("Can not load config resource component-beans.properties in classpath");        } else {            Properties prop = new Properties();            prop.load(is);            is.close();            for (String key : prop.stringPropertyNames()) {                String value = prop.getProperty(key);                if (value != null) {                    System.out.printf("%s = %s %n", key, value);                }            }        }    }}
Testconfig.java

  在Testconfig.java文件中,模拟实现了从classpath中读取配置文件component-beans.properties,接下来创建antoconfig的描述文件auto-config.xml以及component-beans.properties.vm配置文件对应的模板文件(属性名中的点在autoconfig执行的时候会被替换成下划线)。

  通常将配置集中管理,使用中央配置仓库,将可变内容存储在数据库中(文本,DB都可以),然后使用模版引擎(velocity,jsp等)生成最终的配置文件,并且提供http或者其他类型的接口给使用方在应用启动前调用。

2.Apache加密工具类DigestUtils.md5Hex(String str)

  MD5算法是单向不可逆的,目前只可以通过暴力破解来破解。如果应用中需要采用可逆的加密方法,可以采用DES,3DES,AES,RSA 等。MD5常用于用户的登陆密码加密,每次把用户输入的密码用MD5加密后跟数据库中存储的密码进行比较。可逆加密常用于前端与后端参数交互,后端解密参数,查询数据返回给前端。

  MD5加密原理是散列算法,散列算法也称哈希算法。比如10除以3余数为一,4除以3余数也为一,但余数为一的就不知道这个数是哪个了。所以md5不能解密。

二、鉴权配置和初始化

  首先,在component-beans.xml.vm文件中配置了bean,并且在容器启动的时候,执行initial方法,将需要权限验证url添加到includeStr集合中。

apiValue定义

  然后在pipeline-web.xml中配置了ApiAuthValue,保证对系统进行API调用请求的时候,执行ApiAuthValue.java中的invoke回调方法。(回调函数的理解:将函数的一部分功能外包给别人。)

pipeline-web.xml

  接着实现了ApiAuthValve.java中的回调方法

package com.alibaba.tboss.common.services.login;import static com.alibaba.tboss.common.auth.costants.ApiConstants.API_AUTH_NAME;import static com.alibaba.tboss.common.auth.costants.ApiConstants.API_AUTH_SIGNATURE;import static com.alibaba.tboss.common.auth.costants.ApiConstants.API_AUTH_TIEMSTAMP;import java.util.ArrayList;import java.util.List;import java.util.regex.Pattern;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import com.alibaba.citrus.extension.rpc.impl.DefaultResultGenerator;import com.alibaba.citrus.extension.rpc.validation.DefaultErrorContext;import com.alibaba.citrus.extension.rpc.validation.ErrorContext;import com.alibaba.citrus.extension.rpc.validation.ErrorItem;import com.alibaba.citrus.service.pipeline.PipelineContext;import com.alibaba.citrus.service.pipeline.support.AbstractValve;import com.alibaba.fastjson.JSON;import com.alibaba.tboss.common.auth.bo.ApiUserBo;public class ApiAuthValve extends AbstractValve {    private static Logger          logger   = LoggerFactory.getLogger(ApiAuthValve.class);    @Resource    ApiUserBo                      apiUserBo;    @Autowired    private HttpServletRequest     request;    @Autowired    private HttpServletResponse    response;    // 必须定义成 protected static ,否则注入不进来    protected static String[]      includeStr;    protected static List
includes = new ArrayList
(); protected static String[] excludeStr; protected static List
excludes = new ArrayList
(); public void initial() { if (includeStr != null) { for (int i = 0; i < includeStr.length; i++) { includes.add(Pattern.compile(includeStr[i].toLowerCase())); } } if (excludeStr != null) { for (int i = 0; i < excludeStr.length; i++) { excludes.add(Pattern.compile(excludeStr[i].toLowerCase())); } } } @Override public void invoke(PipelineContext pipelineContext) throws Exception { String uri = request.getRequestURI(); try { // isInControl=true表示请求链接需要鉴权 if (isInControl(uri)) { // 外部调用,必须添加的三个参数:apiName、timestamp、signature String apiName = request.getParameter(API_AUTH_NAME); String timestamp = request.getParameter(API_AUTH_TIEMSTAMP); String signature = request.getParameter(API_AUTH_SIGNATURE); // 没有从api_user表匹配权限 apiUserBo.checkAuthorization(apiName, timestamp, signature, uri); } } catch (Exception e) { logger.error(uri + "fail - " + e.getMessage(), e); // 折衷方案,依赖rpc extention ErrorContext errorContext = new DefaultErrorContext(); errorContext.addError(ErrorItem.create("rpc_500", "500", String.format("API auth fail : " + e.getMessage(), request.getRequestURI()))); Object result = new DefaultResultGenerator.GenericWebRPCResult("API auth fail", null, errorContext); response.getWriter().print(JSON.toJSONString(result)); return; } pipelineContext.invokeNext(); } private boolean isInControl(String uri) { boolean control = false; for (Pattern pattern : includes) { if (pattern.matcher(uri.toLowerCase()).matches()) { control = true; break; } } if (control) { for (Pattern pattern : excludes) { if (pattern.matcher(uri.toLowerCase()).matches()) { control = false; break; } } } return control; } public void setRequest(HttpServletRequest request) { this.request = request; } public void setResponse(HttpServletResponse response) { this.response = response; } public String[] getIncludeStr() { return includeStr; } public void setIncludeStr(String[] includeStr) { this.includeStr = includeStr; } public String[] getExcludeStr() { return excludeStr; } public void setExcludeStr(String[] excludeStr) { this.excludeStr = excludeStr; }}
ApiAuthValue.java

  最后,在执行相应的业务逻辑。附鉴权方法的实现类如下:

import org.apache.commons.lang3.time.DateUtils;import com.alibaba.common.lang.MathUtil;import org.apache.commons.codec.digest.DigestUtils;public void checkAuthorization(String apiName, String timestamp, String signature, String uri) {        if(StringUtils.isBlank(apiName) || StringUtils.isBlank(timestamp) || StringUtils.isBlank(signature)) {            throw new ApiAuthException("apiName, timestamp, signature is missing");        }        Date gmtRequest = null;        try {            gmtRequest = DateUtils.parseDate(timestamp, API_AUTH_TIMEFORMAT);        } catch (ParseException e) {            throw new ApiAuthException("Unsupported timestamp format, suggestting as " + API_AUTH_TIMEFORMAT);        }        if (MathUtil.abs(System.currentTimeMillis() - gmtRequest.getTime()) >= 15 * 60 * 1000) {            throw new ApiAuthException("Request has been expired");        }                ApiUser user = getApiUserByName(apiName);        if(user == null) {            throw new ApiAuthException("Api user is not exist");        }        if(!isAuthorized(user, uri)) {            throw new ApiAuthException(String.format("%s has no permission to access uri %s", apiName, uri));        }        String realCode = decode(user.getCode());        String format = String.format("%s%s%s", apiName, timestamp, realCode);        if(!signature.equals(DigestUtils.md5Hex(format))) {            throw new ApiAuthException("Signature is not match");        }    }

配合鉴权的表单提交测试Demo如下:首先需要md5.js和jquery-1.11.3.min.js两个js仓库。表单提交代码如下:

 

    测试Demo              
apiName:
code:
timestamp:
signature
sn:
orderId:
img:
View Code

 

转载地址:http://jzfll.baihongyu.com/

你可能感兴趣的文章
一个月内发现的第六起Linux DDoS木马
查看>>
IDC:全球服务器市场始现低迷
查看>>
是时候说一下SaaS的本质了
查看>>
ThoughtWorks技术雷达发布四大技术趋势
查看>>
乾县智慧城市建设取得新进展
查看>>
车联网将成“北斗”未来一个非常大的应用方向
查看>>
苹果手机定位用户行迹:是否对信息安全构成威胁?
查看>>
医疗大健康行业案例(老人健康实时监测和预警) - 阿里云RDS PostgreSQL最佳实践
查看>>
博科:2017年技术变革与发展的趋势预测
查看>>
CCAI 2017 | 清华大学计算机系教授史元春:科幻与创新
查看>>
东方日升:海外分布式光伏项目经验值得借鉴
查看>>
英国乐购网上银行2000个账户遭窃 现已暂停服务
查看>>
陈旭东用暴雨搞借势营销:工厂被淹 ZUK线上缺货
查看>>
中国第一家大数据资产评估实验室揭牌
查看>>
Fortinet: 全球2016年第四季度全球医疗行业威胁分析与报告
查看>>
深度剖析堆栈
查看>>
零售行业RFID应用解析
查看>>
金风科技澳洲首座20兆瓦光伏电站将于2017年投产
查看>>
Java 代理
查看>>
《Effective Debugging:软件和系统调试的66个有效方法》——第12条:将复杂的测试场景自动化...
查看>>