token考证完成

挪动开辟中一定会触及背景API怎样接见,怎样掌握接见权限,保证体系安全等题目。

引见一下我近来本身做的一个挪动端接见后端API的例子,例子写的很粗拙,然则基础完成了以token auth 为中心的demo。

在完成demo过程当中也找到了不少的好材料,这一篇《APP中用户考证计划》细致的引见了APP用户考证的差别计划。

大致思绪:

APP登录界面输入用户信息登录;效劳端考证登录信息,考证胜利,向APP端发送token,将token保存到数据库或许缓存效劳器中;APP登录胜利后,每次挪用后端API时都须要带着token、时候戳、sign(token+时候戳的md5字符串,sign能够本身定义算法以防备被盗用)信息,以便背景考证接见API权限;后端在接收到APP接见要求时,比对APP发送来的token与缓存效劳器中已存在的token是不是一致,并考证token时效性。

好了,废话少说,上代码:

前端代码(APP,近来写的APP基础都是H5体式格局完成):

<label>用户名</label>
        <input type="text" name="username" id="username" value="" />
        <br/>
        <label>暗码</label>
        <input type="password" name="password" id="password" value="" />
        <input type="button" name="login" id="login" value="登录" />
        
        
        <script type="text/javascript">
            document.getElementById("login").addEventListener('click',function () {
                //alert('hello');
                //ajax提交考证信息到后端
                var username = document.getElementById("username").value;
                var password = document.getElementById("password").value;
                var data = "{\"username\":\"" + username +"\",\"password\":\"" + password + "\"}";
                var url = "/AppTest/loginServlet";
                var wd = "123";
                var headData = ["123","123456789012345","gsfgfgbdf"];
                postData(url,data, headData,function (backdata) {
                    if(backdata != null){
                        console.log("返回的信息为:  " + backdata);
                    }
                },wd);
                
            });
        </script>

这里的ostData运用的是封装好的Ajax函数,下面一并放出代码:

ajax.js:

/*对ajax举行浅易封装,便于每次挪用,省去参数设置*/
function postData(url, data, headData, callback, waitingDialog) {
    mui.ajax(url,{  
        data:data,  
        dataType:'json',  
        type:'post',
        headers: {
            "token" : headData[0],
            "timesamp" : headData[1],
            "sign" : headData[2]
        },
        contentType:"application/x-www-form-urlencoded; charset=utf-8",  
        timeout:20000,  
        success:callback,
        error:function(xhr,type,errorThrown){  
            //waitingDialog.close();
            alert("<网络连接失利,请从新尝试一下>", "毛病", "OK", null);  
        }  
    });
}  

ajax中加上了headers参数,这里加headers参数的目标是,背景运用servlet+filter的体式格局掌握接见,假如将token等其他参数直接和表单数据同时提交,filter在猎取token信息后,servlet就不能猎取到表单数据,这就比较为难了,或许背景运用AOP的体式格局掌握接见权限 ,这个还没有来得及尝试。假如我能把token信息加到于表单数据差别的存储地区就好了,Google后找到了能够把数据加到要求的header中能够完成将token数据与表单数据星散的结果。

过滤器(Java完成 JDK1.8 Tomcat8.5.6):

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import me.wlc.wx.web.tool.Md5;

/**
 * 运用注解标注过滤器
 * @WebFilter将一个完成了javax.servlet.Filte接口的类定义为过滤器
 * 属性filterName声明过滤器的称号,可选
 * 属性urlPatterns指定要过滤 的URL形式,也可运用属性value来声明.(指定要过滤的URL形式是必选属性)
 * urlPatterns="/*" 示意过滤掉一切要求
 */
@WebFilter(filterName="AccessFilter",urlPatterns="/*")
public class AccessFilter implements Filter {

    @Override
    public void destroy() {
        
        System.out.println("过滤器烧毁");

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("实行过滤操纵");
        HttpServletRequest req = (HttpServletRequest) request;
        String uri = req.getRequestURI();
        System.out.println("uri is :  " + uri);
        
        //对要求的uri(即api)举行推断,假如是登录的uri则直接放行,假如是其他api则对sign举行考证操纵
        if( !uri.endsWith("loginServlet") ){
            //从要求的url中掏出token、时候戳、sign
            String token = req.getHeader("token");
            String timesamp = req.getHeader("timesamp");
            String sign = req.getHeader("sign");
            System.out.println("sign is :  " + sign);
            
            StringBuffer requestUrl = req.getRequestURL();
            System.out.println("要求的Url是:   " + requestUrl);
            
            //对token、timesamp 举行md5盘算
            String signMd5 = Md5.getMD5(token + timesamp);
            if(sign.equals(signMd5)){
                //署名经由过程
                chain.doFilter(request, response);
            }else{
                //署名不经由过程,向app后端发送毛病信息,提醒从新登录
                
            }    
        }else{
            //登录操纵
            chain.doFilter(request, response);
        }
        
        //要求经由过程
        //chain.doFilter(request, response);
        
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        
        System.out.println("过滤器初始化");
        
    }

}

后端还没有完成考证token时效性功能,也没有将token存储到缓存效劳器中,这些须要详细计划定下来今后再加上了。再说一句,天生的token保证token值唯一即可,能够运用最轻易的UUID(Java中)。

大致就是如许了,有题目随时提给我哦!

PS:2018年9月28日更新

一向没有登录检察留言,给留言板的列位兄弟道个歉,没有实时复兴

token存储计划:

计划一:运用session的超时时候来掌握token的失效时候

计划二:运用redis存储token的失效时候

计划一适用于单机环境,能够作为小型体系的token时效性考证计划,此计划若处于分布式环境会致使session在分布式机械间的时候差别步,但跟组里的其他工程师沟通,在分布式环境下是不是是还能够同步session?

计划二适用于大型体系,还要运用redis效劳,运用redis存储token但是完成疾速读取token时效数据,若将toke失效时候存储到数据库中,频仍操纵数据库,会影响数据库的相应时候,进而应用程序也会涌现卡顿等状况。

另,token的失效时候应当设置多长须要依据地点项目标实际状况肯定。

    原文作者:912093517
    原文地址: https://segmentfault.com/a/1190000009122246
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞