vlambda博客
学习文章列表

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用


【双十一钜惠:科技人的专属保障】移动端认证保障

——非对称加密及jwt应用



第一时间了解程序员大小事儿


作者:open,从事java开发领域8年,对spring开发框架,缓存服务器,搜索引擎,中间件,代理服务器都有很深的造诣。现专注于项目组内技术研发及架构搭建。

编者按:本次双十一钜惠活动,移动APP、线上系统直面大量客户,那么我们科技人是如何保证数据安全,特别是登陆认证凭据数安全?让我们一起来寻找答案。随着移动APP、微服务架构兴起,JWT技术广泛应用,JWT数据的安全性愈发重要;本篇文章,主要与大家分享利用数据加密保证JWT数据安全应用方案总结,希望热爱技术的伙伴能够从中找到共鸣,得到受益,不当之处请多多批评指教。

01

对称与非对称加密


对称加密:加密和解密的秘钥为同一个,加密速度快、效率高、计算量小算法公开,缺点是安全性低。常用的对称加密算法有DES、3DES(TripleDES)、AES等。

非对称加密:具有公开和私有的一对密钥,公开密钥加密只能私有密钥解密,同样私有密钥加密只有公开密钥能够解密。非对称加密最大的优点是安全性高,缺点是加密速度慢,加密内容有字节数限制,如果加密内容较长需要进行分段加密或其他加密方式进行辅助加密。常见的非对称加密类型有RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)。

对于移动端应用,大多采用前后分离架构,所有数据由原生、h5、vue等终端通过json与后端服务进行交互,对于一些敏感数据(密码),如果使用对称加密,算法和密钥很容易暴露在前端,攻击者能够轻易对加密数据进行破译和伪造,对于用户敏感数据信息安全存在极大的风险。所以需要使用安全的非对称加密算法进行数据加密,下面通过对RSA非对称加密算法的具体应用更深入的理解他的安全性。

0 2

RSA非对称加密具体应用


假设某系统登录模块,前后分离架构,需要进行用户名密码加密传输到后端进行认证,如果利用对称加密,密钥和算法直接通过浏览器即可获取,如果传输数据被截获,很容易反解出用户密码。采用非对称加密会存在此类问题吗?下面模拟登录请求进行测试。

(1)生成一对RSA密钥

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

(2)公钥提供给前端,进行密码加密传输(此例模拟公钥加密)

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

(3)模拟登录请求,后端利用私钥进行解密,成功解密出密码。

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

(4)截获请求利用提供给前端的公钥进行解密,无法解密,程序出现异常。

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

【双十一钜惠:科技人的专属保障】移动端认证保障 ——非对称加密及jwt应用

(5)结论

非对称加密,公钥加密只有私钥能够解密,私钥存储在服务器端,只要私钥不被暴露,加密内容无法被反解出来,能够保护数据传输的安全性。

03

基于RSA非对称算法的jwt安全认证应用


JWT (Json web token), 是为了在网络应用双方进行信息传递执行的一种安全、简洁的基于JSON的开放标准(RFC 7519)。可用于用户认证,jwt是无状态的,较session有更好的扩展性。具体应用如下:

(1)认证流程图

(2)引入相关依赖

        <dependency>

            <groupId>io.jsonwebtoken</groupId>

            <artifactId>jjwt</artifactId>

            <version>0.9.1</version>

        </dependency>

(3)认证通过,生成token(对应图中步骤2)

//指定签名的时候使用的签名算法,也就是header那部分,jwt已对此部分内容进行封装。

 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;

  //创建payload的私有声明(键值对儿,存储业务关键信息,请勿存放关键敏感信息,jwt虽然不能被伪造,但是可以被解密查看)

Map<String, Object> claims = new HashMap<String, Object>();

claims.put("id", "1233456");

//生成签名的时候使用的秘钥secret,这个方法本地封装了的,此密钥一定不能泄露,如果泄露,就能够伪造token了。

String privateKey = "asdfasdfasdfsadfsa";

//生成JWT的时间

long nowMillis = System.currentTimeMillis();

Date now = new Date(nowMillis);

//设置jwt

JwtBuilder builder = Jwts.builder()

    .setClaims(claims)

    //iat: jwt的签发时间

    .setIssuedAt(now)

//代表这个JWT的主体,即它的所有人,可以酌情设置。

     .setSubject("user123")

//设置签名使用的签名算法和签名使用的秘钥

     .signWith(signatureAlgorithm, RSA.genPrivateKey(privateKey));

long expMillis = nowMillis + 60*1000;

Date exp = new Date(expMillis);

//设置过期时间为一分钟。

builder.setExpiration(exp);

String tokenJwt = builder.compact();

return tokenJwt;

(4)将token存入cookie返回(对应图中步骤4)

Cookie cookie = new Cookie("token",tokenJwt);

//单位为秒

cookie .setMaxAge(60*1000);

cookie .setPath("/");

response.addCookie(cookie);

(5)网关添加全局过滤器,校验token。token校验通过后检查是否需要续期,如果需要续期则调用相应服务进行续期(此例为伪代码,直接在网关进行续期)。最后将token解析出的用户关键信息存入header供后端服务使用。(对应图中步骤6)

MultiValueMap<String, HttpCookie> cookies= request.getCookies();

String tokensrcret = null;

HttpCookie tokenCookie = (HttpCookie)(cookies.get("token").get(0));

tokensrcret =tokenCookie.getValue();

if(StringUtils.isNotBlank(tokensrcret)){

   //签名公钥,与生成token的私钥是一对

   String key = "asafasdfsdf";

   //解密jwt

   Claims claims = Jwts.parser()

   //设置签名的秘钥

     .setSigningKey(RSA.genPublicKey(key))

   //设置需要解析的jwt

     .parseClaimsJws(tokensrcret).getBody();

   Date issuedAtDate = claims.getIssuedAt();

   long issatTokenMillis = issuedAtDate.getTime();

   long nowMillis = System.currentTimeMillis();

   //签发日期超过40秒,强制token失效,防止恶意无限刷新token。

   if(nowMillis-issatTokenMillis<45*1000){

       //获取JWT的失效时间

       Date expirateDate = claims.getExpiration();

       long tokenExpirateMillis = expirateDate.getTime();

       if(tokenExpirateMillis-nowMillis<60*60*1000){

           //超过45秒为token继续续期75秒,此处为伪代码,实际可将此部分抽出到认证服务中。

          long expMillis = nowMillis + 75*1000;

          Date exp = new Date(expMillis);

          claims.setExpiration(exp);

          //私钥,注意防止泄露

          String privateKey="qwerq";

          String  token= Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS256,RSA.genPrivateKey(privateKey)).compact();

          //放入cookie返回给终端

          ResponseCookie.ResponseCookieBuilder cookieBuilder = ResponseCookie.from("token",token);

          cookieBuilder.maxAge(75*1000/1000);

                    cookieBuilder.path("/");

         response.addCookie(cookieBuilder.build());

       }

       //将解密出的信息放入header供后端服务使用

 request.addHeader("id",JSONObject.toJSON(claims.get("id")).toString());

 return true;

 }

}

return false;


03

总结


RSA非对称加密结合jwt能够提供安全、简洁的网络数据传输,jwt的无状态性,能够为应用提供更好的扩展性。

科技人需要时刻谨记系统安全红线,规避风险。在日常生活中,我们同样需要为自己、家人和关心的人提供安全的保障。本次双十一钜惠活动,为生活中的各种风险提供各类的保障计划,赶紧扫描下方二维码,选择适合自己、实惠的保险保障。

真爱无价,惠保万家,双十一感恩钜惠!