3

有缺陷放弃

传输密码动态加密解密

这个模块分离至项目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,秘钥>的<key,value>形式存储到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<String ,String> 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


Apache_HertzBeat
227 声望51 粉丝

嗨 ~~