ershoumall使用Gitee社交登录(注意@RequestBody不可有多个)

社交登录

使用oauth2技术。
在这里插入图片描述
在这里插入图片描述

需要解决的问题一:

在社交登录授权登录后,该gitee、weibo用户需要关联本ershoumall系统的会员账户信息ershoumall-member,故需远程调用oauth2login方法。

由于我在远程调用方法中声明了两个实体类,且使用了两次@RequestBody,导致控制台报500错误,仅仅简单显示远程调用具体方法出现问题。没有其他任何说明。如下:

@PostMapping("member/member/oauth2/login")
    public R oauthlogin(@RequestBody GiteeVo giteeVo) throws Exception;

错误举例如下:

@PostMapping(“member/member/oauth2/login”)
public R oauthlogin(@RequestBody AccessToken token,@RequestBody UserInfo) throws Exception;由于注解底层原理特性,一个方法仅允许使用一次@RequestBody注解。故将该两个实体类属性BeanUtils.copyProperties()到新对象giteeVo中。


@Data
public class GiteeVo {

    private String access_token;
    private String token_type;
    private long expires_in;
    private String refresh_token;
    private String scope;
    private long created_at;

// 注意,我合并了。
    private long id;

    private String login;

    private String name;

    private String avatar_url;

    private String url;

    private String html_url;

    private String followers_url;

    private String following_url;

    private String gists_url;

    private String starred_url;

    private String subscriptions_url;

    private String organizations_url;

    private String repos_url;

    private String events_url;

    private String received_events_url;

    private String type;

    private String blog;

    private String weibo;

    private String bio;

    private long public_repos;

    private long public_gists;

    private long followers;

    private long following;

    private long stared;

    private long watched;

    private String updated_at;

    private String email;
}

  1. OAuth2Controller

    @GetMapping("/oauth2/gitee/success")
    public String gitee(@RequestParam("code") String code, HttpSession session, HttpServletResponse servletResponse, HttpServletRequest request) throws Exception {
        Map<String, String> header = new HashMap<>();
        Map<String, String> query = new HashMap<>();


        Map<String, String> map = new HashMap<>();
        map.put("client_id", "6d977af422e89d8b2b58811dcfxx5033ee401ee473562fa66426c59edc173ba9");
        map.put("client_secret", "b07d4364a9a171602332cb3bd20cxxa60ade23526e8fb2c21900b472f8a860db");
        map.put("grant_type", "authorization_code");
        map.put("redirect_uri", "http://auth.xxmall.com/oauth2/gitee/success");

        // todo 检查以上是否加.auth


        map.put("code", code);
        HttpResponse response = HttpUtils.doPost("https://gitee.com", "/oauth/token", "post", header, query, map);
        if (response.getStatusLine().getStatusCode() == 200) {
            String tokenJson = EntityUtils.toString(response.getEntity());
            log.info(tokenJson);
            GiteeAccessToken token = JSON.parseObject(tokenJson, GiteeAccessToken.class);
            Map<String, String> query2 = new HashMap<>();
            query2.put("access_token", token.getAccess_token());
            HttpResponse response_userInfo = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", new HashMap(), query2);
            String giteeUserInfoJson = EntityUtils.toString(response_userInfo.getEntity());
            log.info(giteeUserInfoJson);
            GiteeUserInfo giteeUserInfo = JSON.parseObject(giteeUserInfoJson, GiteeUserInfo.class);

// 针对Gitee,个人独特的处理
            GiteeVo giteeVo = new GiteeVo();
            BeanUtils.copyProperties(token, giteeVo);
            BeanUtils.copyProperties(giteeUserInfo, giteeVo);
     
            R oauthlogin = memberFeignService.oauthlogin(giteeVo);
            if (oauthlogin.getCode() == 0) {
                MemberRespVo data = oauthlogin.getData("data", new TypeReference<MemberRespVo>() {
                });
                log.info("登录成功:用户:{}", data.toString());             
                return "redirect:http://xxshoumall.com";

            } else {
                return "redirect:http://auth.xxshoumall.com/login.html";
            }
        } else {
            return "redirect:http://auth.xxshoumall.com/login.html";
        }
    }
  1. MemberController
    @PostMapping("/oauth2/login")
    public R oauthlogin(@RequestBody GiteeVo giteeVo) throws Exception {
        MemberEntity entity =  memberService.login2(giteeVo);
        if(entity!=null){
            return R.ok().setData(entity);
        }else{
            return R.error(BizCodeEnum.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getCode(),BizCodeEnum.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getMessage());
        }
    }

3.MemberServiceImpl

    
    /**
     * 社交登录
     * @param
     * @return
     * @throws Exception
     */
    @Override
    public MemberEntity login2(GiteeVo giteeVo) throws Exception {
        String uid = String.valueOf(giteeVo.getId()); // 老师的uid是gitee的id,注意类型转换

        //1、判断当前社交用户是否已经登录过系统;
        MemberDao memberDao = this.baseMapper;
        MemberEntity memberEntity = memberDao.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid)); // 实际就是gitee中仅存的id,只是我没有改名
        if (memberEntity != null) {
            //这个用户已经注册
            MemberEntity update = new MemberEntity();
            update.setId(memberEntity.getId());
            update.setAccessToken(giteeVo.getAccess_token());
            update.setExpiresIn(giteeVo.getExpires_in());

            memberDao.updateById(update);

            memberEntity.setAccessToken(giteeVo.getAccess_token());
            memberEntity.setExpiresIn(giteeVo.getExpires_in());
            System.out.println("140...");
            return memberEntity;
        }else{
            //2、没有查到当前社交用户对应的记录我们就需要注册一个
            MemberEntity regist = new MemberEntity();
            try{
                Map<String,String> query = new HashMap<>();
                query.put("access_token",giteeVo.getAccess_token());
//                query.put("uid",String.valueOf(giteeUserInfo.getId())); // gitee这里请求参数不需要携带uid,微博才需要携带
                HttpResponse response = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", new HashMap<String, String>(), query);
                if(response.getStatusLine().getStatusCode() == 200){
                    //查询成功
                    String json = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(json);
                    String name = jsonObject.getString("name");
                    String email = jsonObject.getString("email");
                    regist.setNickname(name);
                    regist.setEmail(email);
                }
            }catch (Exception e){
                System.out.println("----------MemberServiceImpl-login(GiteeAccessToken giteeAccessToken,GiteeUserInfo giteeUserInfo)--------------------------"+e.getMessage());
            }

            regist.setSocialUid(String.valueOf(giteeVo.getId()));
            regist.setAccessToken(giteeVo.getAccess_token());
            regist.setExpiresIn(giteeVo.getExpires_in());
            memberDao.insert(regist);
            System.out.println("171...");
            return regist;
        }
    }

需要解决的问题二:session共享(不同步)问题

温顾:session是存储在服务端的一个对象,服务器创建session对象,传给浏览器一个jsessionId,浏览器通过cookie这个对象存入jsessionId,从此浏览器会携带此cookie对象去请求。

但是:微服务不同服务模块间,session数据不共享,如下实例:
在这里插入图片描述cookie只存在于auth.ershoumall.com该Domain下,在ershoumall.com下不存在,该如何解决(不能跨不同域名共享,或同域名但分布式部署情况不同服务器)捏?

法一:session复制同步。在大型分布式集群系统情况下,它将占用大量玩过带宽,每一台服务器冗余存储全量数据,消耗巨大性能低下。
法二:仅存在客户端cookie中,非常不安全。
法三(较好):利用nginx负载均衡hash一致性,只需要该nginx配置,可以支持水平扩展。缺点:web-server一旦重启会导致session丢失。当服务器水平扩展后,一部分用户路由不到正确的session
法四(采用)统一存储:负载均衡到server再到redis/db集群,后台统一存储session

使用SpringSession,即可帮我将jsessionId自动存入已连接的redis中。

  1. 配置文件中编写spring.session.store为redis,且连好redis
  2. 各服务启动类标明@SessionRedis
  3. 各服务模块分别声明@Confugration配置sessio父子域为.ershoumall.com。

如果访问的父域名都不同,需要单点登录。

手机号/账号密码登录

简洁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值