资讯专栏INFORMATION COLUMN

传输密码动态加密解密(有缺陷放弃)

miguel.jiang / 3188人阅读

摘要:有缺陷放弃传输密码动态加密解密这个模块分离至项目权限管理系统与前后端分离实践,感觉那样写文章太长了找不到重点,分离出来要好点。这里的前后端加密解密下图由于介绍的是动态加密解密传输信息方案,这里并不会涉及之后的签发等。

有缺陷放弃 传输密码动态加密解密

这个模块分离至项目api权限管理系统与前后端分离实践,感觉那样写文章太长了找不到重点,分离出来要好点。

在用户密码登录认证中,明文传输用户输入的密码是不可取的。在没有用https的情况下,这里需要对用户密码加密传输,保证即使密码泄露也不影响。

这里的前后端加密解密下图:

由于介绍的是动态加密解密传输信息方案,这里并不会涉及之后的JWT签发等。

下面是实现细节:
angular 前端发送get动态秘钥请求后会对对象进行监听,在回调函数里获取后端返回的秘钥后再进行加密处理,之后再发送登录请求。在angular我把请求服务化了,下面的代码片段会有点凌乱。

 // 调用获取tokenKey秘钥服务
    this.loginService.getTokenKey().subscribe(
      data => {
        this.responseData = data;
        if (this.responseData.data.tokenKey !== undefined) {
          const tokenKey = this.responseData.data.tokenKey;
          // 调用服务,发送认证请求
          this.loginService.login(this.appId, this.password, tokenKey).subscribe(
            data2 => {
              // 认证成功返回jwt
              this.responseData = data2;
              if (this.responseData.meta.code === 1003 && this.responseData.data.jwt != null) {
                this.authService.updateAuthorizationToken(this.responseData.data.jwt);
                this.authService.updateUid(this.appId);
                this.authService.updateUser(this.responseData.data.user);
                this.router.navigateByUrl("/index");
              } else {
                this.msg = "用户名密码错误";
                this.isDisabled = true;
              }
            },
            error => {
              console.error(error);
              this.msg = error;
              this.isDisabled = true;
            }
          );
        }
      }
    );
@Injectable()
export class LoginService {
  constructor(private httpUtil: HttpUtil) {
  }
  getTokenKey() {
    const url = "account/login?tokenKey=get";
    // 先向后台申请加密tokenKey tokenKey=get
    // const getKeyParam = new HttpParams().set("tokenKey", "get");
    return this.httpUtil.get(url);
  }

  login(appId: string, password: string, tokenKey: string) {
    const url = "account/login";
    tokenKey = CryptoJS.enc.Utf8.parse(tokenKey);
    password = CryptoJS.enc.Utf8.parse(password);
    password = CryptoJS.AES.encrypt(password, tokenKey, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7}).toString();
    console.log(password);
    const param = new HttpParams().append("appId", appId)
      .append("password", password)
      .append("methodName", "login")
      .append("timestamp", new Date().toUTCString());
    return this.httpUtil.post(url, param);
  }
}

后端是在一个filter中对登录注册请求进行拦截,判断其是正常登录注册还是获取动态加密秘钥请求,正常认证就走shiro,判断为获取秘钥则生成16随机码默认AES加密秘钥为约定16位,小于16位会报错,将秘钥以<远程IP,秘钥>的形式存储到redis,设置其有效时间为5秒5秒看自己情况不要太大也不要太短,设置有效期是为了防止被其他人截取到加密密码冒充用户的情况,把风险降更低

 // 判断若为获取登录注册加密动态秘钥请求
        if (isPasswordTokenGet(request)) {
            //动态生成秘钥,redis存储秘钥供之后秘钥验证使用,设置有效期5秒用完即丢弃
            String tokenKey = CommonUtil.getRandomString(16);
            try {
                redisTemplate.opsForValue().set("PASSWORD_TOKEN_KEY_"+request.getRemoteAddr().toUpperCase(),tokenKey,5, TimeUnit.SECONDS);
                // 动态秘钥response返回给前端
                Message message = new Message();
                message.ok(1000,"issued tokenKey success")
                        .addData("tokenKey",tokenKey);
                RequestResponseUtil.responseWrite(JSON.toJSONString(message),response);

            }catch (Exception e) {
                LOGGER.warn(e.getMessage(),e);
                // 动态秘钥response返回给前端
                Message message = new Message();
                message.ok(1000,"issued tokenKey fail");
                RequestResponseUtil.responseWrite(JSON.toJSONString(message),response);
            }
            return false;
        }
// 创建认证信息,其中就有包括获取redis中对应IP的动态秘钥
    private AuthenticationToken createPasswordToken(ServletRequest request) {
        Map map = RequestResponseUtil.getRequestParameters(request);
        String appId = map.get("appId");
        String timestamp = map.get("timestamp");
        String password = map.get("password");
        String host = request.getRemoteAddr();
        String tokenKey = redisTemplate.opsForValue().get("PASSWORD_TOKEN_KEY_"+host.toUpperCase());
        return new PasswordToken(appId,password,timestamp,host,tokenKey);
    }


效果展示




github:
bootshiro
usthe

码云:
bootshiro
usthe



持续更新。。。。。。


分享一波阿里云代金券快速上云

转载请注明 from tomsun28

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69184.html

相关文章

  • 当我们在谈论前端加密时,我们在谈些什么

    摘要:所以我们今天只谈前端加密,一个部分人认为没有意义的工作。在中,认证过程使用了非对称加密算法,非认证过程中使用了对称加密算法。非对称加密上文中我们讨论了前端的哈希加密以及应用的场景。 showImg(https://segmentfault.com/img/bVAhTC); 当然在谈安全。 前端安全是Web安全的一部分,常见的安全问题会有XSS、CSRF、SQL注入等,然而这些已经在程师...

    wizChen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<