精华内容
下载资源
问答
  • admin获取token|刷新token|注销token

    千次阅读 2019-09-18 10:24:24
    //后台调用对象 varadmin={ /** *获取Token *@paramusername用户名 *@parampassword密码 *@paramcallback回调函数 */ getToken:function(username,password,callback){ ...

    //后台调用对象

    var admin = {

     

        /**

         * 获取Token

         * @param username 用户名

         * @param password 密码

         * @param callback 回调函数

         */

        getToken: function(username, password, callback){

            var data = {

                username: username,

                password: password,

                client_id: 'user_client',

                client_secret: 'user_client',

                grant_type:'password'

            };

            config.request.tokenName = false;

            this.get(this.getAuthUrl(), data, function (json) {

                callback(json);

            })

        },

     

        /**

         * 注销Token

         * @param callback 回调函数

         */

        logoutToken: function(callback){

            var data = {

                access_token: cache.data(config.tableName)[config.request.tokenName]

            };

            config.request.tokenName = false;

            this.get(this.getLogoutUrl(), data, function (json) {

                cache.clearTokenCache();

                callback(json);

            })

        },

     

        /**

         * 获取请求头Token

         * @returns {string}

         */

        getHeaderToken: function(){

            var headerToken = "Bearer ";

     

            //刷新Token

            if(this.isNeedRefreshToken(cache.data(config.tableName, "login_timestamp"), cache.data(config.tableName, "expires_in"))){

                this.refreshToken(function (data) {

                    this.addTokenCache(data);

                });

            }

     

            //追加Token参数

            if(config.request.tokenName && cache.data(config.tableName)[config.request.tokenName]){

                headerToken += cache.data(config.tableName)[config.request.tokenName];

            }

     

            return headerToken;

        },

     

        /**

         * 获取Token对象

         */

        getTokenInfo: function(){

            let tokenInfo = {};

     

            //刷新Token

            if(this.isNeedRefreshToken(cache.data(config.tableName, "login_timestamp"), cache.data(config.tableName, "expires_in"))){

                this.refreshToken(function (data) {

                    this.addTokenCache(data);

                });

            }

     

            //追加Token参数

            if(config.request.tokenName && cache.data(config.tableName)[config.request.tokenName]){

                tokenInfo = cache.data(config.tableName);

            }

     

            return tokenInfo;

        },

     

        /**

         * 返回绑定Token的url地址(为避免Token过期,包含Token刷新机制)

         * @param url 待绑定Token的url

         */

        bindTokenUrl: function(url){

     

            //刷新Token

            if(this.isNeedRefreshToken(cache.data(config.tableName, "login_timestamp"), cache.data(config.tableName, "expires_in"))){

                this.refreshToken(function (data) {

                    this.addTokenCache(data);

                });

            }

     

            //追加Token参数

            if(config.request.tokenName && cache.data(config.tableName)[config.request.tokenName]){

                var connectSymbol = "?";

                if(url.indexOf("?") > 0){

                    connectSymbol = "&";

                }

                url = config.web.adminUrl + url + connectSymbol + config.request.tokenName + "=" + cache.data(config.tableName)[config.request.tokenName];

            }

     

            return url;

        },

     

        /**

         * 通过get获取数据

         * @param url 访问地址

         * @param data 参数

         * @param callback 回调函数

         */

        get: function (url, data, callback) {

     

            //url中绑定Token信息

            url = this.bindTokenUrl(url);

     

            $.get(url, data, function (data,status,xhr ) {

                callback(data);

            });

        },

     

        /**

         * 通过getAsync获取数据 同步访问数据

         * @param url 访问地址

         * @param data 参数

         * @param callback 回调函数

         */

        getAsync: function (url, data, callback) {

     

            //url中绑定Token信息

            url = this.bindTokenUrl(url);

     

            $.ajaxSettings.async = false;

            $.get(url, data, function (data) {

                callback(data);

            });

            $.ajaxSettings.async = true;

        },

     

        /**

         * 通过get获取数据

         * @param url 访问地址

         * @param data 参数

         * @param callback 回调函数

         */

        getJSON: function (url, data, callback) {

     

            //url中绑定Token信息

            url = this.bindTokenUrl(url);

     

            $.getJSON(url, data, function (data) {

                callback(data);

            });

        },

     

        /**

         * 通过getAsync 同步获取数据

         * @param url 访问地址

         * @param data 参数

         * @param callback 回调函数

         */

        postAsync: function (url, data, callback) {

     

            //url中绑定Token信息

            url = this.bindTokenUrl(url);

     

            $.ajaxSettings.async = false;

            $.post(url, data, function (data) {

                callback(data);

            });

            $.ajaxSettings.async = true;

        },

     

        /**

         * 通过get获取数据

         * @param url 访问地址

         * @param data 参数

         * @param callback 回调函数

         */

        post: function (url, data, callback) {

     

            //url中绑定Token信息

            url = this.bindTokenUrl(url);

     

            $.post(url, data, function (data) {

                callback(data);

            });

        },

        /**

         * 是否需要刷新Token

         * @param loginTimeStamp 登录时间戳

         * @param expiresIn 过期时间

         */

        isNeedRefreshToken: function (loginTimeStamp, expiresIn) {

            var currentTimeStamp = new Date().getTime();

            var remainTime = expiresIn - (currentTimeStamp - loginTimeStamp);

            if(!isNaN(remainTime) && remainTime <= 120000){

                return true;

            }

            return false;

        },

     

        /**

         * 刷新Token

         * @param refresh_token 刷新Token

         * @param callback

         */

        refreshToken: function(refresh_token, callback){

            var isRefreshToken = config.request.isRefreshToken;

            if(!isRefreshToken || isRefreshToken == "true"){

                config.request.isRefreshToken = "false";

                var data = {

                    refresh_token: refresh_token,

                    client_id: 'user_client',

                    client_secret: 'user_client',

                    grant_type:'refresh_token'

                };

     

                $.ajax({

                    type: "post",

                    data: data,

                    url: this.getAuthUrl(),

                    async: false,

                    dataType: "json",

                    success: function (result) {

                        callback(result);

                    }

                });

     

                //等待下次Token刷新

                setTimeout(function(){

                    config.request.isRefreshToken = "true";

                }, 15000);

            }

        },

     

        /**

         * 获取授权服务地址

         */

        getAuthUrl: function(){

            return config.web.adminUrl + "/" + config.web.authServiceName + "/oauth/token";

        },

     

        /**

         * 获取注销服务地址

         */

        getLogoutUrl: function(){

            return config.web.adminUrl + "/" + config.web.authServiceName + "/oauth/logout";

        },

     

    展开全文
  • 常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别。两种鉴权方式对比session安全性:session是基于cookie进行用户识别的,cookie如果被截获,用户很容易...

    常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别。

    两种鉴权方式对比

    session

    1. 安全性:session是基于cookie进行用户识别的,cookie如果被截获,用户很容易受到跨站请求伪造的攻击。
    2. 扩展性:session是有状态的,是具有IP黏贴性和有中心化特性的,在分布式环境下,虽然每台服务器业务逻辑一样,但是session是保存在各个服务器中的,而且每个服务器内存是不共享的,如果使用session去实现分布式部署的话,需要使用其他的一些技术手段去实现,比如spring session,将session保存在第三方服务中,比如redis,这样一旦第三方服务出现问题,整个验权系统就会奔溃,在电商系统及高并发系统中的集群化处理显然是不合适的。
    3. 抗压能力:通常session是存储在内存中的,每个用户通过认证后都会将session存储在服务器内存中,当用户量增大的情况下服务器的压力也随之增大。

    token

    1. 安全性:浏览器会将接收到的token值存储在Local Storage中,(通过js代码写入Local Storage,通过js获取,并不会像cookie一样自动携带)
    2. 扩展性:token是无状态的,是去中心化的,在分布式环境下,各个服务器中的服务只对token进行数据查询,它不需要在服务端保留用户信息或者会话信息,这意味着用户不需要考虑登录的是哪一台服务器,高效的解决了session扩展性的弊端。
    3. 抗压能力:token与session的不同主要在认证成功后,会对当前用户数据进行加密,生成一个加密字符串token,返还给客户端(服务器端并不进行保存)

    基于token的鉴权方式

    业界常用的授权标准有两种,一种是使用auth2,这种方式更适合于类似第三方授权登录,比如微信、微博、QQ信任登录业务。另一种是oauth,即第三方无需知道用户和密码就可以申请获得该资源的授权,更适用于对用户的权限校验并分配访问权限,比如常见的登录后分配可见资源(按钮、菜单等)类型网站。

    Javashop电商系统 采用的是oauth方式的鉴权标准。我们以系统的应用为例来介绍oauth的方案。

    70a5e81fc5829fef42c0424828530fca.png

    1. 登录

    服务端校验密码,成功后返回access_token和refresh_token,客户端记录上述token。

    2. 访问API

    在访问API之前解析access_token,并且查看是否过期,如果不过 期则请求API,如果过期,则要刷新令牌,在请求API。

    3. 刷新token

    携带有效期的refresh_token换回有效token,如果refresh_token过期,则需要用户重新登录。

    4. 注销

    请求注销api,服务器端和客户端应同时删除token的存储。

    38dd1e0ebe44bbd24f7f73afe3cae666.png

    1. 客户端请求API

    携带access_token信息,如果生成环境不会直接携带access_token,会使用加密后的签名校验。祥见以下防重放机制。

    2. 获取token

    根据环境不同而有不同的获取token方式。

    3. 解析token

    通过JWT工具将token解析。

    4. 由redis读取token

    根据uid拼接key读取access_token, 如果不存在这个用户的token说明已经登出。

    5. 验证token

    判断次token是否属于此uid,判断token是否过期,如果过期则进行以下刷新token的流程。

    6. 注入权限

    如果token验证成功,根据user信息生成权限注入到spring安全上下文中。

    刷新token流程

    54d195f1ee38903c3773d864b67cabd9.png

    1. 客户端请求API

    携带refresh_token,如果是生产环境不会直接携带refresh_token信息,详见以下防重放攻击。

    2. 获取token

    根据环境不同而有不同的获取token方式。

    3. 解析token

    通过JWT工具将token解析。

    4. token读取

    根据uid拼接key读取出access_token,如果不存在这个用户的token说明用户已经登出。

    5. 验证token

    判断此token是否属于此uid,判断token是否已经过期,如果过期,则返回refresh_token过期错误,此时用户需要重新登录。

    6. 刷新token

    如果refresh_token 验证成功,则重新生成access_token和refresh_token,上述有效期以当前时间向后计算,替换此用户在redis中的token,并将token返回给客户端。

    防重放机制

    dd9e814e2a567ab8c4a23e4fa72dbc6e.png

    一、 参数的读取

    1. 在生产环境时,不能直接传递token,而是要传递签名数据,服务器端验签后由Redis中获取签名。

    2. 如果是非生产环境,直接由header中读取token。

    二、 生产环境传递如下参数

    memberid (用户id)

    nonce(随机字串,6位)

    timestamp(当前时间戳,到秒)

    sign= md5( uid+ nonce + timestamp +token )

    三、 验证逻辑

    1. 验证时间戳

    判断时间戳是否起过60s,大于60s则判别为重放功击。

    2. 验证nonce

    首先验证nonce在 reids中是否存在,如果存在,则判别为重放功击,否则将nonce记录在redis中(key为:"nonce"+uid+"_"+nonce),失效时间为60s。

    3. 验证sign

    md5( uid+ nonce + timestamp +token ) 验证是签名是否通过。

    4. 验证token

    通过uid拿到token ,验证逻辑同验权流程。

    当然在不同的业务场景下实现方案是多种多样的,仅以此方案抛转引玉,供大家参考。

    fdba3bc26509d7c0a902aab412726a3c.png
    展开全文
  • token在客户端与服务器端的交互流程Token的优点和思考参考代码:核心代码使用参考,不是全部代码JWT token的组成头部(Header),格式如下:{“typ”: “JWT”,“alg”: “HS256”}由上可知,该token使用HS256加密算法...

    本文你能学到什么?

    token的组成

    token串的生成流程。

    token在客户端与服务器端的交互流程

    Token的优点和思考

    参考代码:核心代码使用参考,不是全部代码

    JWT token的组成

    头部(Header),格式如下:

    {

    “typ”: “JWT”,

    “alg”: “HS256”

    }

    由上可知,该token使用HS256加密算法,将头部使用Base64编码可得到如下个格式的字符串:

    eyJhbGciOiJIUzI1NiJ9

    有效载荷(Playload):

    {

    “iss”: “Online JWT Builder”,

    “iat”: 1416797419,

    “exp”: 1448333419,

    …….

    “userid”:10001

    }

    有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。有效载荷也使用Base64编码得到如下格式的字符串:

    eyJ1c2VyaWQiOjB9

    签名(Signature):

    将Header和Playload拼接生成一个字符串str=“eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOjB9”,使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT,即我们需要的令牌(token),形如:str.”签名字符串”。

    token在服务与客户端的交互流程

    1:客户端通过用户名和密码登录

    2:服务器验证用户名和密码,若通过,生成token返回给客户端。

    3:客户端收到token后以后每次请求的时候都带上这个token,相当于一个令牌,表示我有权限访问了

    4:服务器接收(通常在拦截器中实现)到该token,然后验证该token的合法性(为什么能验证下面说)。若该token合法,则通过请求,若token不合法或者过期,返回请求失败。

    关于Token的思考

    服务如何判断这个token是否合法?

    由上面token的生成可知,token中的签名是由Header和有效载荷通过Base64编码生成再通过加密算法HS256和密钥最终生成签名,这个签名位于JWT的尾部,在服务器端同样对返回过来的JWT的前部分再进行一次签名生成,然后比较这次生成的签名与请求的JWT中的签名是否一致,若一致说明token合法。由于生成签名的密钥是服务器才知道的,所以别人难以伪造。

    token中能放敏感信息吗?

    不能,因为有效载荷是经过Base64编码生成的,并不是加密。所以不能存放敏感信息。

    Token的优点

    (1)相比于session,它无需保存在服务器,不占用服务器内存开销。

    (2)无状态、可拓展性强:比如有3台机器(A、B、C)组成服务器集群,若session存在机器A上,session只能保存在其中一台服务器,此时你便不能访问机器B、C,因为B、C上没有存放该Session,而使用token就能够验证用户请求合法性,并且我再加几台机器也没事,所以可拓展性好就是这个意思。

    (3)由(2)知,这样做可就支持了跨域访问。

    Java实例:JWT token使用

    部分代码来自互联网,找不到原作者了。。

    编写JWT(Java Web Token)操作类:JavaWebToken

    public class JavaWebToken {

    private static Logger log = LoggerFactory.getLogger(JavaWebToken.class);

    //该方法使用HS256算法和Secret:bankgl生成signKey

    private static Key getKeyInstance() {

    //We will sign our JavaWebToken with our ApiKey secret

    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("bankgl");

    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

    return signingKey;

    }

    //使用HS256签名算法和生成的signingKey最终的Token,claims中是有效载荷

    public static String createJavaWebToken(Map claims) {

    return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance()).compact();

    }

    //解析Token,同时也能验证Token,当验证失败返回null

    public static Map parserJavaWebToken(String jwt) {

    try {

    Map jwtClaims =

    Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwt).getBody();

    return jwtClaims;

    } catch (Exception e) {

    log.error("json web token verify failed");

    return null;

    }

    }

    }

    编写登录Conreoller,在服务器端给客户返回token.

    public LoginStatusMessage checkUserAndPassword(

    @RequestParam(value="username",required=true) String username,

    @RequestParam(value="password",required=true) String password,User user,HttpServletRequest request) throws Exception{

    User u = new User();

    //登录成功

    if((u = userService.checkUsernameAndPassword(user)) != null){

    Map m = new HashMap();

    m.put("userid", user.getUserid());

    String token = JavaWebToken.createJavaWebToken(m);

    System.out.println(token);

    LoginStatusMessage lsm = new LoginStatusMessage();

    lsm.setUser(u);

    lsm.setToken(token);

    return lsm;

    };

    //登录失败,返回Null

    return null;

    }

    在拦截器中对请求中的Token验证(部分代码,表示下意思):

    String token = request.getParameter("token");

    if(JavaWebToken.parserJavaWebToken(token) != null){

    //表示token合法

    return true;

    }else{

    //token不合法或者过期

    return false;

    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • 业务场景在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE、REACTJS等构建)使用token与后端接口交互,以达到安全的目的。本文结合stackover以及本身项目实践,试图总结出一个...

    业务场景

    在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE、REACTJS等构建)使用token与后端接口交互,以达到安全的目的。本文结合stackover以及本身项目实践,试图总结出一个通用的,可落地的方案。

    基本思路

    单个token

    token(A)过期设置为15分钟

    前端发起请求,后端验证token(A)是否过期;如果过期,前端发起刷新token请求,后端设置已再次授权标记为true,请求成功

    前端发起请求,后端验证再次授权标记,如果已经再次授权,则拒绝刷新token的请求,请求成功

    如果前端每隔72小时,必须重新登录,后端检查用户最后一次登录日期,如超过72小时,则拒绝刷新token的请求,请求失败

    授权token加上刷新token

    用户仅登录一次,用户改变密码,则废除token,重新登录

    1.0实现

    1.登录成功,返回access_token和refresh_token,客户端缓存此两种token;

    2.使用access_token请求接口资源,成功则调用成功;如果token超时,客户端

    携带refresh_token调用中间件接口获取新的access_token;

    3.中间件接受刷新token的请求后,检查refresh_token是否过期。

    如过期,拒绝刷新,客户端收到该状态后,跳转到登录页;

    如未过期,生成新的access_token和refresh_token并返回给客户端(如有可能,让旧的refresh_token失效),客户端携带新的access_token重新调用上面的资源接口。

    4.客户端退出登录或修改密码后,调用中间件注销旧的token(使access_token和refresh_token失效),同时清空客户端的access_token和refresh_toke。

    后端表

    id user_id client_id client_secret refresh_token expire_in create_date del_flag

    2.0实现

    场景: access_token访问资源 refresh_token授权访问 设置固定时间X必须重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期30分钟)和refresh_token(jwt有效期15天),并缓存到redis(hash-key为token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token,也可以根据sub-key,废除部分设备的token。),设置过期时间为1个月,保证最终所有token都能删除),返回后,客户端缓存此两种token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除);客户端再次携带refresh_token调用中间件接口获取新的access_token;

    3.中间件接受刷新token的请求后,检查refresh_token是否过期。

    如过期,拒绝刷新,删除refresh_token(废除); 客户端收到该状态后,跳转到登录页;

    如未过期,检查缓存中是否有refresh_token(是否被废除),如果有,则生成新的access_token并返回给客户端,客户端接着携带新的access_token重新调用上面的资源接口。

    4.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token和refresh_token(废除)),同时清空客户端侧的access_token和refresh_toke。

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    6.以上3刷新access_token可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:失效,长时间未登录,频繁刷新)

    2.0 变动

    1.登录

    2.登录拦截器

    3.增加刷新access_token接口

    4.退出登录

    5.修改密码

    3.0实现

    场景:自动续期 长时间未使用需重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期30分钟),并缓存到redis(hash-key为access_token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token),设置access_token过期时间为7天,保证最终所有token都能删除),返回后,客户端缓存此token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的access_token,

    再次请求接口资源。

    3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清空客户端侧的access_token。

    4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长时间未登录,频繁刷新)

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    3.0 变动

    1.登录

    2.登录拦截器

    3.退出登录

    4.修改密码

    1.3 场景:token过期重新登录 长时间未使用需重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期7天),并缓存到redis,key为 "user_id:access_token",value为access_token(根据用户id,可以人工废除指定用户全部token),设置缓存过期时间为7天,保证最终所有token都能删除,请求返回后,客户端缓存此access_token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的access_token,

    再次请求接口资源。

    3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清空客户端侧的access_token。

    4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长时间未登录,频繁刷新)

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    1.3 变动

    1.登录

    2.登录拦截器

    3.退出登录

    4.修改密码

    解决方案

    2.0 场景: access_token访问资源 refresh_token授权访问 设置固定时间X必须重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期30分钟)和refresh_token(jwt有效期15天),并缓

    存到redis(hash-key为token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全

    部token,也可以根据sub-key,废除部分设备的token。),设置过期时间为1个月,保证最终所有token都

    能删除),返回后,客户端缓存此两种token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

    token超时,中间件删除access_token(废除);客户端再次携带refresh_token调用中间件接口获取新的

    access_token;

    3.中间件接受刷新token的请求后,检查refresh_token是否过期。

    如过期,拒绝刷新,删除refresh_token(废除); 客户端收到该状态后,跳转到登录页;

    如未过期,检查缓存中是否有refresh_token(是否被废除),如果有,则生成新的access_token并返回给

    客户端,客户端接着携带新的access_token重新调用上面的资源接口。

    4.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token和refresh_token(

    废除)),同时清空客户端侧的access_token和refresh_toke。

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    6.以上3刷新access_token可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(

    拒绝的场景:失效,长时间未登录,频繁刷新)

    2.0 变动

    1.登录

    2.登录拦截器

    3.增加刷新access_token接口

    4.退出登录

    5.修改密码

    3.0 场景:自动续期 长时间未使用需重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期30分钟),并缓存到redis(hash-key为

    access_token,sub-key为手机号,value为设备唯一编号(根据手机号码,可以人工废除全部token,也可以

    根据sub-key,废除部分设备的token。),设置access_token过期时间为1个月,保证最终所有token都能删

    除),返回后,客户端缓存此token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

    token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的

    access_token,

    再次请求接口资源。

    3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清

    空客户端侧的access_token。

    4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长

    时间未登录,频繁刷新)

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    3.0 变动

    1.登录

    2.登录拦截器

    3.退出登录

    4.修改密码

    4.0 场景:token过期重新登录 长时间未使用需重新登录

    1.登录成功,后台jwt生成access_token(jwt有效期7天),并缓存到redis,key为

    "user_id:access_token" + 用户id,value为access_token(根据用户id,可以人工废除指定用户全部

    token),设置缓存过期时间为7天,保证最终所有token都能删除,请求返回后,客户端缓存此

    access_token;

    2.使用access_token请求接口资源,校验成功且redis中存在该access_token(未废除)则调用成功;如果

    token超时,中间件删除access_token(废除),同时生成新的access_token并返回。客户端收到新的

    access_token,

    再次请求接口资源。

    3.客户端退出登录或修改密码后,调用中间件注销旧的token(中间件删除access_token(废除)),同时清

    空客户端侧的access_token。

    4.以上2 可以增加根据登录时间判断最长X时间必须重新登录,此时则拒绝刷新token。(拒绝的场景:长

    时间未登录,频繁刷新)

    5.如手机丢失,可以根据手机号人工废除指定用户设备关联的token。

    4.0 变动

    1.登录

    2.登录拦截器

    3.退出登录

    4.修改密码

    最终实现

    后端

    在登录接口中 如果校验账号密码成功 则根据用户id和用户类型创建jwt token(有效期设置为-1,即永不过期),得到A

    更新登录日期(当前时间new Date()即可)(业务上可选),得到B

    在redis中缓存key为ACCESS_TOKEN:userId:A(加上A是为了防止用户多个客户端登录 造成token覆盖),value为B的毫秒数(转换成字符串类型),过期时间为7天(7 * 24 * 60 * 60)

    在登录结果中返回json格式为{"result":"success","token": A}

    用户在接口请求header中携带token进行登录,后端在所有接口前置拦截器进行拦截,作用是解析token 拿到userId和用户类型(用户调用业务接口只需要传token即可), 如果解析失败(抛出SignatureException),则返回json(code = 0 ,info= Token验证不通过, errorCode = '1001'); 此外如果解析成功,验证redis中key为ACCESS_TOKEN:userId:A 是否存在 如果不存在 则返回json(code = 0 ,info= 会话过期请重新登录, errorCode = '1002'); 如果缓存key存在,则自动续7天超时时间(value不变),实现频繁登录用户免登陆。

    把userId和用户类型放入request参数中 接口方法中可以直接拿到登录用户信息

    如果是修改密码或退出登录 则废除access_tokens(删除key)

    前端(VUE)

    用户登录成功,则把username存入cookie中,key为loginUser;把token存入cookie中,key为accessToken 把token存入Vuex全局状态中

    进入首页

    展开全文
  • Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。因为数字签名的存在,这些信息...
  • JWT官网: [https://jwt.io/][https_jwt.io] JWT(Java版)的github地址:...什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).**定义了一种简洁...
  • JWT简介 :json Web Token(缩写JWT)是目前最流行的跨域认证解决方案session登录的认证方案是看,用户从客户端传递用户名和密码登录信息,服务端认证后将信息储存在session中,将session_id放入cookie中,以后访问...
  • 我最近也在做这个一个解决方案是oauth2 中把JwtTokenStore 改成RedisTokenStore ,然后登出的时候清redis另外还是借用的redis用户每次登录生成token,我还是在redis中把这个token存储登出的时候清除redis中存储的...
  • 退出登录时,如果不使JWT Token失效会产生如下2个问题问题1-未过期的token还是可以用要是用户在多个设备登录了,而且本地保存了token。当一个地方丢弃token,但是这个token要是没有过期,那之前token还是可以用的。...
  • 注销和access_token

    2012-12-10 16:40:18
    <p>I'm trying to simply log a user out of fb before continuing on to log them out of my system. ...access_token=$access_token"; </code></pre> <p>Is there a better way of doing this? </div>
  • I am using jwt plugin and strategy in hapijs.I am able to create jwt token while login user and authenticate other API using the same token through 'jwt' strategy.I am setting the token in request.sta...
  • 1.JWT简介JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。2 JSON Web Token的应用...
  • JWT token 如何实现注销或登出

    千次阅读 2020-03-12 18:46:19
    但是令牌生命周期短意味着用户因令牌已过期而不断被注销。 旋转代币。也许引入刷新令牌的概念。当用户登录时,为他们提供JWT和刷新令牌。将刷新令牌存储在数据库中。对于经过身份验证的请求,客户端可以使用JWT,...
  • JWT(JSON Web Token)是目前最流行的认证方案之一。博客园、各种技术公众号隔三差五就会推一篇JWT相关的文章,真的多如牛毛。但我对JWT有点困惑,今天写出来跟大家探讨探讨,不要喷哈。JWT原理本文默认读者已经对...
  • #helps.py中 class LoginRequiredAuthentication(BaseAuthentication): def authenticate(self, request): token = request.META.get('HTTP_TOKEN') #请求头中拿token if token: try: payload = jwt.decod
  • 前端用户登录的思路 在网络上,用户访问有两种状态,匿名(没...第一次登入 需要获取token 第二次登入 (1 token 还在有效期 2token已经期 3用户注销token) 这里涉及到登入后保存token的问题 涉及到 token 的储存地址
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...
  • JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案 原理 JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,由客户端来保存登录信息。此后,客户端每次与服务器通信,都要带上这个 JWT。...
  • JWT(JSON WEB TOKEN)的特点是无状态,通常用来作为验证登录以及鉴权,在这一方面,JWT体现出了他的优点。然而,如果使用JWT实现,用户主动注销、强制登出(禁止登陆)、忘记密码、修改密码,JWT续签等方面的需求,就会让...
  • 流程1.使用微信小程序登录和获取用户信息Api接口2.把Api获取的用户资料和code发送给django后端3....后端通过JSON web token方式登录,把token和用户id传回小程序6.小程序将token和用户id保存在storag...
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 273
精华内容 109
关键字:

注销token