用户密码登录接口和Token

用户密码登录接口

集群:多台机子同时部署一个服务

客户端负载均衡:Ribbon

1.物料:
(1)"用户登录页面.md"接口文档
(2)用户微服务工程(dm-user-provider,dm-user-consumer)
(2)生成token机制原理
(3)缓存用户信息和token信息
(4)修改数据库脚本:

SELECT * FROM dm_user WHERE phone= 'cj88sdj@163.com' AND PASSWORD = 'e10adc3949ba59abbe56e057f20f883e'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O9UG8Dcj-1573225333163)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573140660109.png)]

2.实现用户密码登录接口
思路1:使用到dm-user-provider,dm-user-consumer,dm-common
思路2:redisUtils.get(tokenKey)方法代表的含义:判断redis中是否存在该对象

步骤1:
dm-common/dm-common-dao/mapper/DmUserMapper接口

public DmUser checkLoginByPassword(@Param(value = "phone") String phone, @Param(value = "password") String password) throws Exception;

dm-common/dm-common-dao/resources/DmUserMapper.xml

<select id="checkLoginByPassword" resultType="cn.dm.pojo.DmUser">
		select
		    id as id,
		    phone as phone,
		    wxUserId as wxUserId,
		    realName as realName,
		    nickName as nickName,
		    sex as sex,
		    idCard as idCard,
		    birthday as birthday,
		    createdTime as createdTime,
		    updatedTime as updatedTime,
		    hobby as hobby
		from dm_user
		where phone=#{phone} and password=#{password}
</select>

步骤2:dm-common/dm-common-client/RestDmUserClient
(1)加入:

@RequestMapping(value = "/checkLoginByPassword", method = RequestMethod.POST)
public DmUser checkLoginByPassword(@RequestBody DmUser dmUser) throws Exception;

@RequestMapping(value = "/generateToken", method = RequestMethod.POST)
public String generateToken(@RequestBody DmUser dmUser) throws Exception;

(2)实现:DmUserClientFallBack客户端代码

(3)本地构建

步骤3:
dm-user-provider/RestDmUserService

@RestController
public class RestDmUserService {
@Autowired
private DmUserMapper dmUserMapper;

@RequestMapping(value = "/checkLoginByPassword",method = RequestMethod.POST)
public DmUser checkLoginByPassword(@RequestBody DmUser dmUser)throws Exception{
	return dmUserMapper.checkLoginByPassword(dmUser.getPhone(),dmUser.getPassword());
}
}

dm-user-provider/RestDmTokenService

@RestController
public class RestDmTokenService {
    private String tokenPrefix = "token";

    @RequestMapping(value = "/generateToken", method = RequestMethod.POST)
    public String generateToken(@RequestBody DmUser dmUser) {
        StringBuilder sb = new StringBuilder();
        sb.append(tokenPrefix + "-");
        sb.append("PC-" + "-");
        String info = MD5.getMd5(EmptyUtils.isEmpty(dmUser.getPhone()) ? dmUser.getWxUserId() : dmUser.getPhone(), 32);
        sb.append(info + "-");
        sb.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "-");
        sb.append(UUID.randomUUID().toString().substring(0, 6));
        return sb.toString();
    }
}

步骤4:创建dm-user-consumer/DmUserController

@RestController
@RequestMapping("/api")
public class DmUserController {

    @Autowired
    private DmLoginService dmLoginService;

    @RequestMapping(value = "/p/login",method = RequestMethod.POST)
    public Dto loginByPassword(@RequestBody DmUser dmUser) throws Exception {
        dmUser.setPassword(MD5.getMd5(dmUser.getPassword(),32));//32为加“盐”
        Object[] results = dmLoginService.login(dmUser);
        if (EmptyUtils.isEmpty(results)) {
            return DtoUtil.returnFail("登陆失败","0000");
        }else {
            return DtoUtil.returnSuccess("登陆成功",results);
        }
    }
}

步骤五:dm-user-consumer/DmLoginService

/**
  * 账号密码登陆
  *
  * @param dmUser
  * @return
  * @throws Exception
  */
  public Object[] login(DmUser dmUser) throws Exception;

步骤六:dm-user-consumer/DmLoginServiceImpl

@Component
public class DmLoginServiceImpl implements DmLoginService {
    @Autowired
    private RestDmUserClient restDmUserClient;

    @Autowired
    private RestDmImageClient restDmImageClient;

    @Autowired
    private RedisUtils redisUtils;


    @Override
    public Object[] login(DmUser user) throws Exception {


        //1.通过用户名和密码两个参数到数据库里获取用户对象,并进行校验
        DmUser dmUser = restDmUserClient.checkLoginByPassword(user);
        //2.判空校验
        if (EmptyUtils.isEmpty(dmUser)) {
            return null;
        }
        //3.定义dmUserVO,并组装
        DmUserVO dmUserVO = new DmUserVO();

        //4.将数据库中的用户对象复制到dmUserVO中

        BeanUtils.copyProperties(dmUser, dmUserVO);

        //5.更新用户id
        dmUserVO.setUserId(dmUser.getId());


        //6.通过用户id查询图片库对象
        List<DmImage> dmImageList = restDmImageClient.queryDmImageList(dmUser.getId(),
                Constants.Image.ImageType.normal,
                Constants.Image.ImageCategory.user);

        //7.判空校验,并更新图片id和图片URL
        if (EmptyUtils.isNotEmpty(dmImageList)) {
            dmUserVO.setImageId(dmImageList.get(0).getId());
            dmUserVO.setImgUrl(dmImageList.get(0).getImgUrl());
        }

        //8.调用restDmUserClient中的generateToken()方法,生成token
        String token = this.generateToken(dmUser);

        //9.(重要!)将token和用户对象保存在redis中
        this.saveToken(token, dmUserVO);

        //10.组装Vo
        TokenVO tokenVO = new TokenVO(token, Constants.Redis_Expire.SESSION_TIMEOUT, System.currentTimeMillis());

        //11.返回用户VO,tokenVO
        return new Object[]{dmUserVO, tokenVO};
    }

    private String generateToken(DmUser dmUser)throws Exception {
        return restDmUserClient.generateToken(dmUser);
    }


    /**
     * (置换token)
     *  将token和用户对象保存在redis中
     */
    private void saveToken(String token, DmUserVO dmUserVO) {
        String tokenKey = Constants.USER_TOKEN_PREFIX + dmUserVO.getUserId();
        String tokenValue = null;


        //1.判断如果redis中包含token,则删除原有的token
        if ((tokenValue = (String) redisUtils.get(tokenKey)) != null) {
            redisUtils.delete(tokenKey);
        }


        //2.重新在redis中生成key为tokenKey,value为token的值
        redisUtils.set(tokenKey, Constants.Redis_Expire.SESSION_TIMEOUT, token);

        //3.在redis中塞入key为token,value为用户对象的值。
        redisUtils.set(token, Constants.Redis_Expire.SESSION_TIMEOUT, JSON.toJSONString(dmUserVO));
    }
}

打开Redis
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bWCDTgpY-1573225333164)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573223104221.png)]

测试:
http://localhost:7100/api/p/login

设置:
headers:Content-Type application/json

{
"phone":"cj88sdj@163.com",
"password":"123456"
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d2lnLVCP-1573225333165)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573223327871.png)]

此时,已经生成了token

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KxvQG48v-1573225333165)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573223422648.png)]

(userToken:)文件夹的形式保存 (token为value)

//在redis中生成两对键值对
U_id:token
token:user
//但凡redis存储池的时候,只要加个冒号,它就以文件夹的形式显示在redis当中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M8ANLDaV-1573225333166)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573223867077.png)]

此处为PC端生成的token(以token为key找到对象)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lh7q2hKs-1573225333167)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1573224294298.png)]
失效时间TTL,若超过失效时间,需要重新登录,置换token

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值