谷粒学院-单点登录(sso)

cookie

注意:只有主域名相同,浏览器在访问时才会携带对应的 cookie
是由服务器发送给客户端(浏览器)的少量信息
作用
cookie是键值对形式存储的少量信息
我们知道,平时上网时都是使用无状态的HTTP协议传输出数据,这意味着客户端与服务端在数据传送完成后就会中断连接。这时我们就需要一个一直保持会话连接的机制。在session出现前,cookie就完全充当了这种角色。也就是,cookie的小量信息能帮助我们跟踪会话。一般该信息记录用户身份。
原理
客户端请求服务器时,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。而客户端浏览器会把Cookie保存起来。当浏览器再请求服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器通过检查该Cookie来获取用户状态。

单点登录

单点登录三种实现方式

  • session广播实现
    即session复制,登录一个模块后,将信息存入session,复制session到其它模块中,复制会消耗资源,适合小型项目.
  • Redis+Cookie实现
    在项目中的某个模块进行登录
    将用户登录信息存入Redis,key随机生成(uuid),value: 用户信息(可以是登录凭证token,在从表中查询userId)
    将Redis中生成的key存入cookie中
    访问项目其它模块,发送请求带着cookie进行发送,获取cookie,从cookie中获取key值,到Redis中查询,如果查询到数据就登录
  • token实现
    在项目中某个模块进行登录,登陆后生成IWT字符串,把字符串返回
    1、通过cookie返回
    2、通过地址栏返回
    当用户去访问其它模块时,每次访问都带着字符串,在访问模块中获取字符串,从字符串中获取用户信息,如果获取到就登录
    如果想设置过期时间,可以设置Redis的过期时间
    session默认过期时间30min

jwt组成:JWT头部、有效载荷、签名

1、用户注册

1、定义RegisterVo

@Data
@ApiModel(value="注册对象", description="注册对象")
public class RegisterVo {

    @ApiModelProperty(value = "昵称")
    private String nickname;

    @ApiModelProperty(value = "手机号")
    private String mobile;

    @ApiModelProperty(value = "密码")
    private String password;

//    @ApiModelProperty(value = "验证码")
//    private String code;
}

2、UcenterMemberController

    //注册
    @PostMapping("register")
    public R Register(@RequestBody RegisterVo registerVo){
        ucenterMemberService.register(registerVo);
        return R.ok();
    }

3、UcenterMemberServiceImpl

    //注册
    @Override
    public void register(RegisterVo registerVo) {
        //将数据加入到数据库中
        String mobile = registerVo.getMobile();  //手机号
        String nickname = registerVo.getNickname();  //昵称
        String password = registerVo.getPassword();  //密码
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(nickname) || StringUtils.isEmpty(password)){
            throw new GuliException(20001, "注册失败");
        }
        //判断手机号是否有重复,重复的不进行注册
        QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile", registerVo.getMobile());
        Integer count = baseMapper.selectCount(wrapper);
        if(count > 0){
            //该手机号已经被注册过了
            throw new GuliException(20001, "注册失败,该账号已被注册!");
        }
        //向数据库中添加数据
        UcenterMember ucenterMember = new UcenterMember();
        ucenterMember.setMobile(registerVo.getMobile());
        //密码需要加密
        ucenterMember.setPassword(MD5.encrypt(registerVo.getPassword()));
        ucenterMember.setNickname(registerVo.getNickname());
        //是否禁用
        ucenterMember.setIsDisabled(false);  //不被禁用
        ucenterMember.setAvatar("https://online-teach-file.oss-cn-beijing.aliyuncs.com/cms/2019/11/14/297acd3b-b592-4cfb-a446-a28310369675.jpg");
        baseMapper.insert(ucenterMember);
    }

2、用户登录

1、UcenterMemberController

    //登录,在数据库中查询用户名和密码
    @PostMapping("login")
    public R loginUser(@RequestBody UcenterMember member){
        //调用service方法实现登录
        String token = ucenterMemberService.login(member);
        return R.ok().data("token", token);
    }

2、UcenterMemberServiceImpl

    @Override
    public String login(UcenterMember member) {
        String mobile = member.getMobile();
        String password = member.getPassword();
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)){
            throw new GuliException(20001, "登录失败");
        }

        //判断手机号是否正确
        QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile", mobile);
        UcenterMember mobileMember = baseMapper.selectOne(wrapper);
        //判断查出来的用户是否为空
        if(mobileMember == null){
            throw new GuliException(20001, "登录失败,账号有误!");
        }
        //判断密码,数据库存储的密码是密文,MD5加密后的
        if(!MD5.encrypt(password).equals(mobileMember.getPassword())){
            throw new GuliException(20001, "登录失败,密码错误!");
        }
        //判断用户是否禁用
        if(mobileMember.getIsDisabled()){
            throw new GuliException(20001, "登录失败,该用户已被禁用!");
        }
        //登录成功
        //生成token字符串,使用jwt工具类
        String token = JwtUtils.getJwtToken(mobileMember.getId(), mobileMember.getNickname());
        return token;
    }

3、生成jwt

    //生成token字符串的方法
    public static String getJwtToken(String id, String nickname){

        String JwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                .setSubject("guli-user")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))

                .claim("id", id)  //设置token主体部分 ,存储用户信息
                .claim("nickname", nickname)

                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }

4、前端
login.js

  //登录
  submitLogin(userInfo) {
    return request({
      url: `/educenter/member/login`,
      method: 'post',
      data: userInfo
    })
  },
    //根据token获取用户信息
  getLoginInfo() {
    return request({
      url: `/educenter/member/getMemberInfo`,
      method: 'get',
     // headers: {'token': cookie.get('guli_token')}
    })
    //headers: {'token': cookie.get('guli_token')} 
  }

login.vue


    data () {
      return {
        user:{
          mobile:'',
          password:''
        },
        //获取用户信息
        loginInfo:{}
      }
    },
    methods: {
      submitLogin(){
            loginApi.submitLogin(this.user).then(response => {
              cookie.set('guli_token', response.data.data.token, {domain: 'localhost'})
              //登录成功根据token获取用户信息
                loginApi.getLoginInfo().then(response => {
                  
                  this.loginInfo = JSON.stringify(response.data.data.userInfo)
                  //将用户信息记录cookie
                  cookie.set('guli_ucenter', this.loginInfo, { domain: 'localhost' })
                  //跳转页面
                  window.location.href = "/";
                })
            })
      },

将jwt存入cookie中

5、根据jwt获取用户信息
UcenterMemberController

    @ApiOperation(value = "根据token获取登录信息")
    @GetMapping("getMemberInfo")
    public R getLoginInfo(HttpServletRequest request){
        try {
            //调用jwt方法,request头信息
            String memberId = JwtUtils.getMemberIdByJwtToken(request);
            UcenterMember member = ucenterMemberService.getById(memberId);
            System.out.println(member);
            return R.ok().data("userInfo", member);
        }catch (Exception e){
            e.printStackTrace();
            throw new GuliException(20001,"error");
        }
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值