App接口之Token令牌实现

《App接口之Token令牌实现》
转载请注明来自 傻小孩b_移动开发http://www.jianshu.com/users/d388bcf9c4d3)喜欢的可以关注我,不定期总结文章!您的支持是我的动力哈!

1、目的

众所周知,在web端中,Token(令牌)只是作为防止用户重复提交表单的作用而存在。但是对于App客户端而言,Token却充当着另一种角色,类似现实生活中代表每个人的角色认证、或者类似浏览器cookie代表你访问网站的角色认证。前提,在有用户系统的应用中,在每次访问接口的时候,为了避免接口裸露被被无止境的请求攻击,往往我们会利用一种机制,过滤一切非应用用户端的非合法请求。首先我们不可能每次利用账号密码作为我们的过滤标准(会存在被抓包密码泄露风险),因此便有
Token(令牌)的存在。即在存在这里的Token是指在指定有效时间内可以代表用户角色,具有请求接口的权限。

当然,这里有开发者会提问,为什么不适用session。理论上是可以的,只是如果是有接触过这部分的移动开发者,session本地是不好处理的,并且完全依赖
session,会被黑客截取后模拟请求,依然会存在被攻击的风险。

2、实现思路

这里我不做加密方式选择的举例,这里只是做了简单的做了不可逆的MD5加密方式(账号+时间戳)。首先web框架是利用(spring + struct2 + mybatis),简单说明下实现思路:

1、用户登录。请求登录接口,如果账号密码核对正确,会根据账号和时间戳进行Md5加密生成Token

2、服务端双向保存token。服务端根据有效时间内生成对应的token之后,服务端双向保存了Memcache中(
Memcache 是一种分布式缓存存储机制,这里我就不详细说明了),最后通过登录接口返回Token信息至客户端中
3、客户端保存返回Token。
客户端通过登录接口成功返回的token,保存的内存中,在每次请求接口都要携带这个token,进行接口请求。

具体思路图如下所示:

token_1.png

token_2.png

3、案例

(1)登录接口实现

    /**
     * 用户登录
     * @throws IOException 
     */
    public void login() throws IOException{
        
        System.out.println("- AppUserManagerAction -" + "login");
        
        String token = TokenUtils.setToken(testAccount);
        System.out.println("账号 " + testAccount + "生成的token:"+token);
        
        JSONObject json = new JSONObject();
        json.put("result", "0");
        json.put("reason", "用户");
        json.put("token", token);
        
        this.getResponse().setContentType("text/plain");
        this.getResponse().setCharacterEncoding("UTF-8");
        this.getResponse().getWriter().write(json.toString());
        this.getResponse().getWriter().flush();
    }

(2)token生成

    /**
     * 为了登陆 或 刷新 Token 生成对应token
     */
    public static String setToken(String account){
        
        String token = generateToken(account);
        
        // 存储正反向
        MemcacheManager.set(account + TOKEN_MARKER, token,TOKEN_VAILD_TIME);
        MemcacheManager.set(token,account + TOKEN_MARKER,TOKEN_VAILD_TIME);

        return token;
    }

(3)struct2 请求拦截

首先在接口请求中,为了对token进行验证,这里是直接在
struct2中写了一个拦截器对请求接口用户Token的验证,有疑问的可以自己谷歌搜索下struct2自定义拦截器


/**
 * Token 拦截器 用于检测Token是否过去,过期直接不执行Action
 * @author wsy
 *
 */
public class TokenInterceptor extends AbstractInterceptor {
    

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        
        System.out.println("-- TokenInterceptor --");
        
        Object action = invocation.getAction();
        if (action instanceof MngUserAction || action instanceof AppUserManagerAction) {
            
            if (invocation.getProxy().getActionName().equals("login")) {
                System.out.println("-- TokenInterceptor -- " + "login 不需要拦截");
                return invocation.invoke();
            }
          
        }
        
        // 取得请求相关的ActionContext实例  
        ActionContext actionContext = invocation.getInvocationContext();  
        
        HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
        HttpServletResponse response = (HttpServletResponse)actionContext.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);  
        
        if (TokenUtils.isVaild(request)) {
            System.out.println("token 有效");
            invocation.invoke();
        }else{
            System.out.println("token 过期");
            
            JSONObject json = new JSONObject();
            json.put("result", "002");
            json.put("reason", "Token 过期");

            response.setContentType("text/plain");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(json.toString());
            response.getWriter().flush();
        }
        
        
        return null;
    }

}

(4)struct2 配置

    <!-- struts 设置默认配置 -->
    <package name="struts-shop" extends="struts-default">
        <interceptors>
            <!-- 默认拦截器 -->
            <interceptor name="authority" class="employee.utils.TokenInterceptor" />

            <!-- 拦截器栈 -->
            <interceptor-stack name="myStack">
                <interceptor-ref name="defaultStack" />
                <interceptor-ref name="authority" />
            </interceptor-stack>

        </interceptors>
        <default-interceptor-ref name="myStack" />
    </package>

    <package name="/employee/application/action" namespace="/employee/application/action"
        extends="struts-shop">

        <action name="login" class="employee.application.action.AppUserManagerAction"
            method="login" />
        <action name="getPersonInfo" class="employee.application.action.AppUserManagerAction"
            method="getPersonInfo"/>

    </package>

4、总结

当然在正式平台,加密方式不会这么简单,具体可以看下
http://blog.csdn.net/jack85986370/article/details/51362278 这篇文章,非对称加密就有很强的加密方式,通过公钥与私钥进行信息加密。有什么问题可以联系笔者,欢迎技术交流哈~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,657评论 18 139
  • 1. 微服务架构介绍 1.1 什么是微服务架构? 形像一点来说,微服务架构就像搭积木,每个微服务都是一个零件,并使...
    静修佛缘阅读 6,643评论 0 39
  • 本文目录:一、单体应用 VS 微服务二、微服务常见安全认证方案三、JWT介绍四、OAuth 2.0 介绍五、思考总...
    挨踢的懒猫阅读 17,972评论 5 29
  • 转载本文需注明出处:微信公众号EAWorld,违者必究。 本文目录: 一、单体应用 VS 微服务 二、微服务常见安...
    72a1f772fe47阅读 8,556评论 3 25
  • 无论任何时候,都不要对一个人太好,因为你终有一天会发现,对一个人好,时间久了,那个人是会习惯的,然后把这一切看作是...
    你倒是发个光呀阅读 116评论 0 0