其他分享
首页 > 其他分享> > Day423.Oauth2&分布式Session -谷粒商城

Day423.Oauth2&分布式Session -谷粒商城

作者:互联网

一、Oauth2

1、介绍

授权流程图示

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


2、接入步骤

以微博为例 官方地址

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


3、代码举例

@Data
public class SocialUser {
    private String access_token;
    private String remind_in;
    private long expires_in;
    private String uid;
    private String isRealName;
}
@Slf4j
@Controller	
public class OAuth2Controller {

    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping(value = "/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code, HttpSession session) throws Exception {

        Map<String, String> map = new HashMap<>();
        map.put("client_id","2077705774");
        map.put("client_secret","40af02bd1c7e435ba6a6e9cd3bf799fd");
        map.put("grant_type","authorization_code");
        map.put("redirect_uri","http://auth.achangmall.com/oauth2.0/weibo/success");
        map.put("code",code);

        //1、根据用户授权返回的code换取access_token
        HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<>(), map, new HashMap<>());

        //2、处理
        if (response.getStatusLine().getStatusCode() == 200) {
            //获取到了access_token,转为通用社交登录对象
            String json = EntityUtils.toString(response.getEntity());
            //String json = JSON.toJSONString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);

            //知道了哪个社交用户
            //1)、当前用户如果是第一次进网站,自动注册进来(为当前社交用户生成一个会员信息,以后这个社交账号就对应指定的会员)
            //登录或者注册这个社交用户
            System.out.println(socialUser.getAccess_token());
            //调用远程服务
            R oauthLogin = memberFeignService.oauthLogin(socialUser);
            if (oauthLogin.getCode() == 0) {
                MemberResponseVo data = oauthLogin.getData("data", new TypeReference<MemberResponseVo>() {});
                log.info("登录成功:用户信息:{}",data.toString());

                //1、第一次使用session,命令浏览器保存卡号,JSESSIONID这个cookie
                //以后浏览器访问哪个网站就会带上这个网站的cookie
                //TODO 1、默认发的令牌。当前域(解决子域session共享问题)
                //TODO 2、使用JSON的序列化方式来序列化对象到Redis中
                session.setAttribute("userInfo",data);

                //2、登录成功跳回首页
                return "redirect:http://achangmall.com";
            } else {
                return "redirect:http://auth.achangmall.com/login.html";
            }
        } else {
            return "redirect:http://auth.achangmall.com/login.html";
        }
    }

}
/**
	 * 社交登录UID
	 */
private String socialUid;

/**
	 * 社交登录TOKEN
	 */
private String accessToken;

/**
	 * 社交登录过期时间
	 */
private long expiresIn;
@PostMapping(value = "/oauth2/login")
public R oauthLogin(@RequestBody SocialUser socialUser) throws Exception {

    MemberEntity memberEntity = memberService.login(socialUser);

    if (memberEntity != null) {
        return R.ok().setData(memberEntity);
    } else {
        return R.error();
    }
}
@Override
public MemberEntity login(SocialUser socialUser) throws Exception {

    //具有登录和注册逻辑
    String uid = socialUser.getUid();

    //1、判断当前社交用户是否已经登录过系统
    MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));

    if (memberEntity != null) {
        //这个用户已经注册过
        //更新用户的访问令牌的时间和access_token
        MemberEntity update = new MemberEntity();
        update.setId(memberEntity.getId());
        update.setAccessToken(socialUser.getAccess_token());
        update.setExpiresIn(socialUser.getExpires_in());
        this.baseMapper.updateById(update);

        memberEntity.setAccessToken(socialUser.getAccess_token());
        memberEntity.setExpiresIn(socialUser.getExpires_in());
        return memberEntity;
    } else {
        //2、没有查到当前社交用户对应的记录我们就需要注册一个
        MemberEntity register = new MemberEntity();
        //3、查询当前社交用户的社交账号信息(昵称、性别等)
        Map<String,String> query = new HashMap<>();
        query.put("access_token",socialUser.getAccess_token());
        query.put("uid",socialUser.getUid());
        HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "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 gender = jsonObject.getString("gender");
            String profileImageUrl = jsonObject.getString("profile_image_url");

            register.setNickname(name);
            register.setGender("m".equals(gender)?1:0);
            register.setHeader(profileImageUrl);
            register.setCreateTime(new Date());
            register.setSocialUid(socialUser.getUid());
            register.setAccessToken(socialUser.getAccess_token());
            register.setExpiresIn(socialUser.getExpires_in());

            //把用户信息插入到数据库中
            this.baseMapper.insert(register);

        }
        return register;
    }

}

二、分布式Session

1、Session共享问题

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


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


2、Session共享问题解决方案

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9KfXLrVL-1634566930483)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211018220339460.png)]

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

通过对请求ip进行hash后获取对应值,根据值来让这个ip访问某个服务的时候,都对一个服务进行访问,保证都在一个服务的session
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvq6zKs4-1634566930486)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211018215242142.png)]

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

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

当浏览器请求服务之后,服务会返回浏览器一个卡信息,并指定放大域名,我们并将Session信息存储到redis中,下次,让浏览器请求我们所有的服务的时候都携带卡,每个服务都去redis去获取对应这个卡的Session信息,这样子就可以解决服务之间共享Session的问题

接下来我们通过SpringSession 来实现redis+session共享问题


标签:code,Oauth2,String,socialUser,用户,token,Session,com,Day423
来源: https://blog.csdn.net/qq_43284469/article/details/120836233