7×24小时服务热线 171 9866 1244
栏目列表
推荐内容

webapi鉴权使用token令牌

时间:2018-11-21 21:24来源: 作者:江海 点击:

一为什么使用Token验证:



在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认

证,那么这就需要用户提供一些信息,比如用户名密码等,但是为了安全起见让用户暴露的明文密码次数越少越好,我们一般在web项目中,大多数采用保

存的session中,然后在存一份到cookie中,来保持用户的会话有效性,但是会在客户端关闭时丢失,还有过期问题。但是app更像一个离线客户端, 因为

它的用户数据保存在本地,可以实现免登陆等,只在它拿数据的时候 提交认证信息就行了 。


二什么场景使用Token验证:


现在很多基于restful的api接口都有个登录的设计,也就是在发起正式的请求之前先通过一个登录的请求接口,申请一个叫做token的东西。申请成功后,后面其他的请求都要带上这个token,服务端通过这个token验证请求的合法性。这个token通常都有一个有效期,一般就是几个小时。




三Token验证有什么特点

1.无状态、可扩展

2.支持移动设备

3.跨程序调用

4.安全




四Token验证的原理

基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中。用户登录后向服务器提供用户认证信息(如账户和密码),服务器认证完后给客户端返回一个Token令牌,用户再次获取信息时,带上此令牌,如果令牌正取,则返回数据。对于获取Token信息后,访问用户相关接口,客户端请求的url需要带上如下参数:

   时间戳:timestamp

   Token令牌:token

然后将所有用户请求的参数按照字母排序(包括timestamp,token),然后更具MD5加密(可以加点盐),全部大写,生成sign签名,这就是所说的url签名算法。然后登陆后每次调用用户信息时,带上sign,timestamp,token参数。




五Token如何生成


token实例


/**

 * Token 的 Model 类,可以增加字段提高安全性,例如时间戳、url 签名

 * @author ScienJus

 * @date 2015/7/31.

 */

public class TokenModel {

 

    // 用户 id

    private long userId;

 

    // 随机生成的 uuid

    private String token;

 

    public TokenModel (long userId, String token) {

        this.userId = userId;

        this.token = token;

    }

 

    public long getUserId () {

        return userId;

    }

 

    public void setUserId (long userId) {

        this.userId = userId;

    }

 

    public String getToken () {

        return token;

    }

 

    public void setToken (String token) {

        this.token = token;

    }

}



/**

 * 对 token 进行操作的接口

 * @author ScienJus

 * @date 2015/7/31.

 */

public interface TokenManager {

 

    /**

     * 创建一个 token 关联上指定用户

     * @param userId 指定用户的 id

     * @return 生成的 token

     */

    public TokenModel createToken (long userId);

 

    /**

     * 检查 token 是否有效

     * @param model token

     * @return 是否有效

     */

    public boolean checkToken (TokenModel model);

 

    /**

     * 从字符串中解析 token

     * @param authentication 加密后的字符串

     * @return

     */

    public TokenModel getToken (String authentication);

 

    /**

     * 清除 token

     * @param userId 登录用户的 id

     */

    public void deleteToken (long userId);

 

}

 

/**

 * 通过 Redis 存储和验证 token 的实现类

 * @author ScienJus

 * @date 2015/7/31.

 */

@Component

public class RedisTokenManager implements TokenManager {

 

    private RedisTemplate redis;

 

    @Autowired

    public void setRedis (RedisTemplate redis) {

        this.redis = redis;

        // 泛型设置成 Long 后必须更改对应的序列化方案

        redis.setKeySerializer (new JdkSerializationRedisSerializer ());

    }

 

    public TokenModel createToken (long userId) {

        // 使用 uuid 作为源 token

        String token = UUID.randomUUID ().toString ().replace ("-", "");

        TokenModel model = new TokenModel (userId, token);

        // 存储到 redis 并设置过期时间

        redis.boundValueOps (userId).set (token, Constants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);

        return model;

    }

 

    public TokenModel getToken (String authentication) {

        if (authentication == null || authentication.length () == 0) {

            return null;

        }

        String [] param = authentication.split ("_");

        if (param.length != 2) {

            return null;

        }

        // 使用 userId 和源 token 简单拼接成的 token,可以增加加密措施

        long userId = Long.parseLong (param [0]);

        String token = param [1];

        return new TokenModel (userId, token);

    }

 

    public boolean checkToken (TokenModel model) {

        if (model == null) {

            return false;

        }

        String token = redis.boundValueOps (model.getUserId ()).get ();

        if (token == null || !token.equals (model.getToken ())) {

            return false;

        }

        // 如果验证成功,说明此用户进行了一次有效操作,延长 token 的过期时间

        redis.boundValueOps (model.getUserId ()).expire (Constants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);

        return true;

    }

 

    public void deleteToken (long userId) {

        redis.delete (userId);

    }

}




--------------------- 

作者:小鱼破浪 

来源:CSDN 

原文:https://blog.csdn.net/m0_38124977/article/details/80963703 

版权声明:本文为博主原创文章,转载请附上博文链接!


(责任编辑:江海)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
关闭
171 9866 1244 工作日:9:00-18:00
点击这里给我发消息

邮箱:
abit@design.com