引言

在上一节《果然新鲜电商项目(21)- 会员注册功能》,主要讲解如何实现会员注册功能,目的主要还是讲解Feign客户端的调用。

本文主要讲解微服务接口的安全问题,使用DTO如何细分接口中的实体。

1.问题引入

我们看看目前项目中注册接口:
在这里插入图片描述
其中里面的请求实体类如下:

@Data
@ApiModel(value = "用户中注册")
public class UserEntity {

	/**
	 * userid
	 */
	@ApiModelProperty(value = "用户id")
	private Long userid;
	/**
	 * 手机号码
	 */
	@ApiModelProperty(value = "手机号码")
	private String mobile;
	/**
	 * 邮箱
	 */
	@ApiModelProperty(value = "邮箱")
	private String email;
	/**
	 * 密码
	 */
	@ApiModelProperty(value = "密码")
	private String password;
	/**
	 * 用户名称
	 */
	@ApiModelProperty(value = "用户名称")
	private String userName;
	/**
	 * 性别 0 男 1女
	 */
	@ApiModelProperty(value = "用户性别")
	private char sex;
	/**
	 * 年龄
	 */
	@ApiModelProperty(value = "用户年龄")
	private Long age;
	/**
	 * 注册时间
	 */
	@ApiModelProperty(value = "创建时间")
	private Date createTime;
	/**
	 * 修改时间
	 *
	 */
	@ApiModelProperty(value = "修改时间")
	private Date updateTime;
	/**
	 * 账号是否可以用 1 正常 0冻结
	 */
	@ApiModelProperty(value = "账号是否可以用 1 正常 0冻结")
	private char is_avalible;
	/**
	 * 用户头像
	 */
	@ApiModelProperty(value = " 用户头像")
	private String pic_img;
	/**
	 * 用户关联 QQ 开放ID
	 */
	@ApiModelProperty(value = "用户关联 QQ 开放ID")
	private Date qq_openid;
	/**
	 * 用户关联 微信 开放ID
	 */
	@ApiModelProperty(value = "用户关联 微信 开放ID")
	private Date WX_OPENID;
}


是否想过,请求的实体类是和数据库的实体类是一模一样的,这样会不会造成安全的问题?譬如我需要增加一个字段isVip(表示是否为会员),那请求者如果是非会员,通过抓包,设置为true,那岂不是会造成数据安全的问题么?其实,我们需要改造一下请求的实体内容,让其与数据库对应的实体类有所区别。

2.何为VO、DO、DTO?

在日常的项目开发中:

  • VO对应于页面上需要显示的数据(表单)
  • DO对应于数据库中存储的数据(数据表)
  • DTO对应于除二者之外需要进行接口形式传递的数据。
    在传统的项目中,一般不使用DTO和VO的原因无非以下几个:

项目太小,对于一种业务实体,封装成一个DO就够了。

  1. 并不熟悉DTOVO,更不知道他们之间的区别。
  2. 了解DO\DTO\VO之间的区别,但是懒得用。
  3. 直接进入主题,修改我们的项目。

3.项目改造

首先需要构建新的新的模块:guoranxinxian-shop-api-dto,并删除旧的模块guoranxinxian-shop-api-entity:
在这里插入图片描述
除此,在guoranxinxian-shop-common-core模块,添加DTO转换工具类:

package com.guoranxinxian.util;

public class BeanUtils<Dto, Do> {

    /**
     * dot 转换为Do 工具类
     *
     * @param dtoEntity
     * @param doClass
     * @return
     */
    public static <Do> Do dtoToDo(Object dtoEntity, Class<Do> doClass) {
        // 判断dto是否为空!
        if (dtoEntity == null) {
            return null;
        }
        // 判断DoClass 是否为空
        if (doClass == null) {
            return null;
        }
        try {
            Do newInstance = doClass.newInstance();
            org.springframework.beans.BeanUtils.copyProperties(dtoEntity, newInstance);
            // Dto转换Do
            return newInstance;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * do 转换为Dto 工具类
     *
     * @param dtoClass
     * @param doEntity
     * @return
     */
    public static <Dto> Dto doToDto(Object doEntity, Class<Dto> dtoClass) {
        // 判断dto是否为空!
        if (doEntity == null) {
            return null;
        }
        // 判断DoClass 是否为空
        if (dtoClass == null) {
            return null;
        }
        try {
            Dto newInstance = dtoClass.newInstance();
            org.springframework.beans.BeanUtils.copyProperties(doEntity, newInstance);
            // Dto转换Do
            return newInstance;
        } catch (Exception e) {
            return null;
        }
    }
    // 后面集合类型带封装
}

3.1 会员微服务改造

3.1.1 新增VO、DO

1.在会员DTO模块下,新建两个包:input(输入参数,请求参数)、output(输出参数,返回响应参数):
在这里插入图片描述
2.修改guoranxinxian-shop-api-member-entity中的UserEntity->UserInDTO,并把UserInDTO复制到第一步的“输入参数”包里,改造内容如下:

package com.guoranxinxian.member.dto.input;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * description: 用户输入DTO
 */
@Data
@ApiModel(value = "用户信息实体类")
public class UserInDTO {

    /**
     * userid
     */
    @ApiModelProperty(value = "用户id")
    private Long userId;
    /**
     * 手机号码
     */
    @ApiModelProperty(value = "手机号码")
    private String mobile;
    /**
     * 邮箱
     */
    @ApiModelProperty(value = "邮箱")
    private String email;
    /**
     * 密码
     */
    @ApiModelProperty(value = "密码")
    private String password;
    /**
     * 用户名称
     */
    @ApiModelProperty(value = "用户名称")
    private String userName;
    /**
     * 性别 0 男 1女
     */
    @ApiModelProperty(value = "用户性别")
    private char sex;
    /**
     * 年龄
     */
    @ApiModelProperty(value = "用户年龄")
    private Integer age;

    /**
     * 用户头像
     */
    @ApiModelProperty(value = " 用户头像")
    private String picImg;
    /**
     * 用户关联 QQ 开放ID
     */
    @ApiModelProperty(value = "用户关联 QQ 开放ID")
    private String qqOpenId;
    /**
     * 用户关联 微信 开放ID
     */
    @ApiModelProperty(value = "用户关联 微信 开放ID")
    private String wxOpenId;

}


3.修改guoranxinxian-shop-api-member-entity中UserEntity->UserOutDTO,并把UserOutDTO复制到第一步的“输出参数”包里,改造内容如下:

package com.guoranxinxian.member.dto.output;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Date;

/**
 * description: 响应返回参数
 */
@Data
@ApiModel(value = "用户返回参数")
public class UserOutDTO {

    /**
     * userid
     */
    @ApiModelProperty(value = "用户id")
    private Long userId;
    /**
     * 手机号码
     */
    @ApiModelProperty(value = "手机号码")
    private String mobile;
    /**
     * 邮箱
     */
    @ApiModelProperty(value = "邮箱")
    private String email;
    /**
     * 用户名称
     */
    @ApiModelProperty(value = "用户名称")
    private String userName;
    /**
     * 性别 0 男 1女
     */
    @ApiModelProperty(value = "用户性别")
    private char sex;
    /**
     * 年龄
     */
    @ApiModelProperty(value = "用户年龄")
    private Integer age;
    /**
     * 注册时间
     */
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    /**
     * 修改时间
     *
     */
    @ApiModelProperty(value = "修改时间")
    private Date updateTime;
    /**
     * 账号是否可以用 1 正常 0冻结
     */
    @ApiModelProperty(value = "账号是否可以用 1 正常 0冻结")
    private char isAvalible;
    /**
     * 用户头像
     */
    @ApiModelProperty(value = " 用户头像")
    private String picImg;
    /**
     * 用户关联 QQ 开放ID
     */
    @ApiModelProperty(value = "用户关联 QQ 开放ID")
    private String qqOpenId;
    /**
     * 用户关联 微信 开放ID
     */
    @ApiModelProperty(value = "用户关联 微信 开放ID")
    private String wxOpenId;

}


4.在会员服务guoranxinxian-shop-service-member,新建UserDo(DO实体类)

package com.guoranxinxian.entity;

import lombok.Data;

import java.util.Date;

@Data
public class UserDo {

    /**
     * userid
     */

    private Long userId;
    /**
     * 手机号码
     */
    private String mobile;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 密码
     */
    private String password;
    /**
     * 用户名称
     */
    private String userName;
    /**
     * 性别 0 男 1女
     */
    private char sex;
    /**
     * 年龄
     */
    private Long age;
    /**
     * 注册时间
     */
    private Date createTime;
    /**
     * 修改时间
     *
     */
    private Date updateTime;
    /**
     * 账号是否可以用 1 正常 0冻结
     */
    private char isAvalible;
    /**
     * 用户头像
     */
    private String picImg;
    /**
     * 用户关联 QQ 开放ID
     */
    private String qqOpenid;
    /**
     * 用户关联 微信 开放ID
     */
    private String wxOpenid;
}


3.1.2 替换之前的实体类

1.替换注册接口的实体类

替换前
在这里插入图片描述
替换后
在这里插入图片描述
2.替换查询手机号是否存在接口的实体类:

改造前:
在这里插入图片描述
改造后:
在这里插入图片描述

3.2 微信微服务改造

过程大致同上!

4. 测试

1.启动微信项目,成功:
在这里插入图片描述
2.启动会员项目,成功:
在这里插入图片描述
公众号测试,成功!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.总结

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐