登录逻辑学习

用户需要有什么样的信息。

-- ----------------------------
-- 1、用户信息表
-- ----------------------------
drop table if exists sys_user;
create table if not exists sys_user
(
    user_id     int8,
    user_name   varchar(30)  not null,
    nick_name   varchar(30)  not null,
    user_type   varchar(10)  default 'sys_user'::varchar,
    email       varchar(50)  default ''::varchar,
    phonenumber varchar(11)  default ''::varchar,
    sex         char         default '0'::bpchar,
    avatar      int8,
    password    varchar(100) default ''::varchar,
    status      char         default '0'::bpchar,
    del_flag    char         default '0'::bpchar,
    login_ip    varchar(128) default ''::varchar,
    login_date  timestamp,
    create_by   int8,
    create_time timestamp,
    update_by   int8,
    update_time timestamp,
    remark      varchar(500) default null::varchar,
    constraint "sys_user_pk" primary key (user_id)
    );


comment on table sys_user               is '用户信息表';
comment on column sys_user.user_id      is '用户ID';
comment on column sys_user.user_name    is '用户账号';
comment on column sys_user.nick_name    is '用户昵称';
comment on column sys_user.user_type    is '用户类型(sys_user系统用户)';
comment on column sys_user.email        is '用户邮箱';
comment on column sys_user.phonenumber  is '手机号码';
comment on column sys_user.sex          is '用户性别(0男 1女 2未知)';
comment on column sys_user.avatar       is '头像地址';
comment on column sys_user.password     is '密码';
comment on column sys_user.status       is '帐号状态(0正常 1停用)';
comment on column sys_user.del_flag     is '删除标志(0代表存在 2代表删除)';
comment on column sys_user.login_ip     is '最后登陆IP';
comment on column sys_user.login_date   is '最后登陆时间';
comment on column sys_user.create_by    is '创建者';
comment on column sys_user.create_time  is '创建时间';
comment on column sys_user.update_by    is '更新者';
comment on column sys_user.update_time  is '更新时间';
comment on column sys_user.remark       is '备注';

-- ----------------------------

-- 初始化-用户信息表数据
-- ----------------------------
insert into sys_user values(1, 'admin', 'eminem', 'sys_user', 'crazyLionLi@163.com', '15888888888', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(),  1, now(), null, null, '管理员');
insert into sys_user values(2, 'xie', '卡特琳娜', 'sys_user', 'crazyLionLi@qq.com',  '15666666666', '1', null, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', now(),  1, now(), null, null, '测试员');

其中constraint “sys_user_pk” primary key (user_id):

创建表时,将 “sys_user_pk” 约束设置为该表的主键,主键的列为 user_id。这意味着在表中,每个唯一的 user_id 值都将唯一标识一行,并且不能重复。通过将 “sys_user_pk” 约束设置为主键,可以确保在执行插入、更新或删除操作时,数据库系统将确保 user_id 的唯一性。

创建系统授权表-规定登录类型,登录id

-- ----------------------------
-- 系统授权表
-- ----------------------------
drop table if exists sys_client;
create table sys_client (
                            id                  int8,
                            client_id           varchar(64)   default ''::varchar,
                            client_key          varchar(32)   default ''::varchar,
                            client_secret       varchar(255)  default ''::varchar,
                            grant_type          varchar(255)  default ''::varchar,
                            device_type         varchar(32)   default ''::varchar,
                            active_timeout      int4          default 1800,
                            timeout             int4          default 604800,
                            status              char(1)       default '0'::bpchar,
                            del_flag            char(1)       default '0'::bpchar,
                            create_by           int8,
                            create_time         timestamp,
                            update_by           int8,
                            update_time         timestamp,
                            constraint sys_client_pk primary key (id)
);

comment on table sys_client                         is '系统授权表';
comment on column sys_client.id                     is '主建';
comment on column sys_client.client_id              is '客户端id';
comment on column sys_client.client_key             is '客户端key';
comment on column sys_client.client_secret          is '客户端秘钥';
comment on column sys_client.grant_type             is '授权类型';
comment on column sys_client.device_type            is '设备类型';
comment on column sys_client.active_timeout         is 'token活跃超时时间';
comment on column sys_client.timeout                is 'token固定超时';
comment on column sys_client.status                 is '状态(0正常 1停用)';
comment on column sys_client.del_flag               is '删除标志(0代表存在 2代表删除)';
comment on column sys_client.create_by              is '创建者';
comment on column sys_client.create_time            is '创建时间';
comment on column sys_client.update_by              is '更新者';
comment on column sys_client.update_time            is '更新时间';

insert into sys_client values (1, 'e5cd7e4891bf95d1d19206ce24a7b32e', 'pc', 'pc123', 'password,social', 'pc', 1800, 604800, 0, 0, 1, now(), 1, now());
insert into sys_client values (2, '428a8310cd442757ae699df5d894f051', 'app', 'app123', 'password,sms,social', 'app', 1800, 604800, 0, 0, 1, now(), 1, now());

登录

package com.xie.web.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import com.xie.common.core.domain.R;
import com.xie.common.core.domain.model.LoginBody;
import com.xie.common.core.utils.StringUtils;
import com.xie.system.domain.SysClient;
import com.xie.system.service.impl.SysClientService;
import com.xie.web.domain.LoginVo;
import com.xie.web.service.IAuthStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @作者:xie
 * @时间:2023/7/6 15:38
 */

@Slf4j
@SaIgnore
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/auth")
public class AuthController {

    private final SysClientService sysClientService;

    @PostMapping("/login")
    public R<LoginVo> Login(@Validated @RequestBody LoginBody loginBody){
        String clientId = loginBody.getClientId();
        String grantType = loginBody.getGrantType();
        SysClient sysClient = sysClientService.queryByClientId(clientId);
        if(ObjectUtil.isNull(sysClient) || !StringUtils.contains(sysClient.getGrantType(),grantType)){
            log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
            return R.fail("auth.grant.type.error");
        }
        // 登录
        return R.ok(IAuthStrategy.login(loginBody, sysClient));
    }

}

判断客户端被授权的pc,app是否一致

    /**
     * 查询客户端管理
     */
    @Override
    public SysClient queryByClientId(String clientId) {
        return sysClientMapper.selectOne(
                new LambdaQueryWrapper<SysClient>()
                        .eq(SysClient::getClientId, clientId)
        );
    }

面向接口-配置登录策略 - password登录

package com.xie.web.service;

import com.xie.common.core.domain.model.LoginBody;
import com.xie.common.core.exception.ServiceException;
import com.xie.common.core.utils.SpringUtils;
import com.xie.system.domain.SysClient;
import com.xie.web.domain.LoginVo;

/**
 * @作者:xie
 * @时间:2023/7/6 21:43
 */
public interface IAuthStrategy {
    String BASE_NAME = "AuthStrategy";


    static LoginVo login(LoginBody loginBody, SysClient sysClient) {
        // 授权类型和客户端id
        String clientId = loginBody.getClientId();
        String grantType = loginBody.getGrantType();
        String beanName = grantType + BASE_NAME;
        if (!SpringUtils.containsBean(beanName)) {
            throw new ServiceException("授权类型不正确!");
        }
        IAuthStrategy instance = SpringUtils.getBean(beanName);
        instance.validate(loginBody);
        return instance.login(clientId, loginBody, sysClient);
    }

    /**
     * 参数校验
     */
    void validate(LoginBody loginBody);

    /**
     * 登录
     */
    LoginVo login(String clientId, LoginBody loginBody, SysClient client);



}

password登录策略

package com.xie.web.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xie.common.core.constant.UserStatus;
import com.xie.common.core.domain.model.LoginBody;
import com.xie.common.core.domain.model.LoginUser;
import com.xie.common.core.enums.LoginType;
import com.xie.common.core.exception.UserException;
import com.xie.common.core.utils.ValidatorUtils;
import com.xie.common.core.validate.auth.PasswordGroup;
import com.xie.common.satoken.utils.LoginHelper;
import com.xie.system.domain.SysClient;
import com.xie.system.domain.SysUser;
import com.xie.system.domain.vo.SysUserVo;
import com.xie.system.mapper.SysUserMapper;
import com.xie.web.domain.LoginVo;
import com.xie.web.service.IAuthStrategy;
import com.xie.web.service.SysLoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @作者:xie
 * @时间:2023/7/6 22:20
 */
@Slf4j
@Service("password" + IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class PasswordAuthStrategy implements IAuthStrategy{

    private final SysUserMapper userMapper;
    private final SysLoginService loginService;

    @Override
    public void validate(LoginBody loginBody) {
        ValidatorUtils.validate(loginBody, PasswordGroup.class);
    }

    @Override
    public LoginVo login(String clientId, LoginBody loginBody, SysClient client) {
        String password = loginBody.getPassword();
        String username = loginBody.getUsername();

        SysUserVo  user = loadByUserName(username);
        loginService.checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
        // 此处可根据登录用户的数据不同 自行创建 loginUser
        LoginUser loginUser = loginService.buildLoginUser(user);
        SaLoginModel model = new SaLoginModel();
        model.setDevice(client.getDeviceType());
        // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
        // 例如: 后台用户30分钟过期 app用户1天过期
        model.setTimeout(client.getTimeout());
        model.setActiveTimeout(client.getActiveTimeout());
        // 生成token
        LoginHelper.login(loginUser, model);
        LoginVo loginVo = new LoginVo();
        loginVo.setAccessToken(StpUtil.getTokenValue());
        loginVo.setExpireIn(StpUtil.getTokenTimeout());
        return loginVo;

    }

    private SysUserVo loadByUserName(String username) {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .select(SysUser::getUserName,SysUser::getStatus)
                .eq(SysUser::getUserName,username));
        if (ObjectUtil.isNull(sysUser)) {
            log.info("登录用户:{} 不存在.", username);
            throw new UserException("user.not.exists", username);
        } else if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus())) {
            log.info("登录用户:{} 已被停用.", username);
            throw new UserException("user.blocked", username);
        }
        return userMapper.selectUserByUserName(username);
    }
}

参考RuoYi-Vue-Plus

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值