一、参考文档
OAuth2.0授权认证
二、原理:
①概念原理:
②实际操作时的原理图:
三、以POSTMAN为例对链接进行测试
① 引导需要授权的用户到如下地址(在前端页面链接设置一下URL):
URL:
https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
其中
YOUR_CLIENT_ID、
YOUR_REGISTERED_REDIRECT_URI分别代表下图中APP KEY和授权回调页:
② 运行页面登录后,页面跳转至 YOUR_REGISTERED_REDIRECT_URI/?code=CODE,获取CODE,利用postman测试以下链接:
https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
其中
YOUR_CLIENT_ID、
YOUR_CLIENT_SECRET分别代表APP KEY和APP Secret,
YOUR_REGISTERED_REDIRECT_URI代表
授权回调页,code则为CODE授权令牌
:
③ 换取Access Token
有了Access Token我们可以通过各种接口获取用户的各种信息,可查看此API文档
四、具体代码编写
①OAuth2Controller类的编写
@Controller
public class OAuth2Controller {
@Autowired
MemberFeignSerivce memberFeignSerivce;
@GetMapping( "/oauth2.0/weibo/success")
public String weibo(@RequestParam("code") String code) throws Exception {
//1、根据code换取accessToken
Map<String,String> map = new HashMap<>();
map.put("client_id","21*********6");
map.put("client_secret","65ae****************e30a");
map.put("grant_type","authorization_code");
map.put("redirect_uri","http://auth.gulimall.com/oauth2.0/weibo/success");
map.put("code",code);
HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<String, String>(), new HashMap<String, String>(), map);
//2、处理微博登陆成功的回调
System.out.println(response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode()==200){
//将返回的json数据变成对象
String json = EntityUtils.toString(response.getEntity());
System.out.println("返回json数据:"+json);
SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
//如果当前用户是第一次登录则自动注册为本网站用户(为当前社交用户生成一个信息账号,以后社交账号对应指定会员)
//登录或注册这个账户
R oauthlogin = memberFeignSerivce.oauthlogin(socialUser);
if (oauthlogin.getCode()==0){
MemberResVo data = oauthlogin.getData("data", new TypeReference<MemberResVo>() {
});
System.out.println("登陆成功:"+ data.toString());
return "redirect:http://gulimall.com";
}else {
return "redirect:http://auth.gulimall.com/login.html";
}
}else {
return "redirect:http://auth.gulimall.com/login.html";
}
}
}
②使用远程调用功能
@FeignClient("gulimall-member")
public interface MemberFeignSerivce {
@PostMapping("/member/member/oauth2/login")
public R oauthlogin(@RequestBody SocialUser socialUser);
}
@RestController
@RequestMapping("member/member")
public class MemberController {
@Autowired
private MemberService memberService;
@PostMapping("/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(BizCodeEnume.LOGIN_PASSWORD_INVAILD_EXCEPTION.getCode(),BizCodeEnume.LOGIN_PASSWORD_INVAILD_EXCEPTION.getMsg());
}
}
}
③MemberService接口编写和实现类
public interface MemberService extends IService<MemberEntity> {
MemberEntity login(SocialUser socialUser) throws Exception;
}
@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {
@Resource
MemberLevelDao memberLevelDao;
@Override
public MemberEntity login(SocialUser socialUser) throws Exception{
//登录和合并逻辑
String uid = socialUser.getUid();
//1、判断当前社交用户是否已经登陆过
MemberDao baseMapper = this.baseMapper;
//查找当前社区用户的账号uid
MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
//则表明已注册过
if (memberEntity != null) {
MemberEntity update = new MemberEntity();
update.setId(memberEntity.getId());
update.setAccessToken(socialUser.getAccess_token());
update.setExpiresIn(socialUser.getExpires_in());
//仅仅是更新本次的令牌号码和过期时间
baseMapper.updateById(update);
//返回最新的本次的令牌号码和过期时间
memberEntity.setAccessToken(socialUser.getAccess_token());
memberEntity.setExpiresIn(socialUser.getExpires_in());
return memberEntity;
} else {
//2、没查到当前用户,则需要注册
MemberEntity regist = new MemberEntity();
try {
//查询当前社交用户的社交信息资料
HashMap<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");
//......
regist.setNickname(name);
regist.setGender("m".equals(gender) ? 1 : 0);
//.......
}
} catch (Exception e) {
e.printStackTrace();
}
regist.setSocialUid(socialUser.getUid());
regist.setAccessToken(socialUser.getAccess_token());
regist.setExpiresIn(socialUser.getExpires_in());
//插入数据库
baseMapper.insert(regist);
return regist;
}
}
}
③所需要的实体类
@ToString
@Data
public class MemberResVo {
private Long id;
/**
* 会员等级id
*/
private Long levelId;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 昵称
*/
private String nickname;
/**
* 手机号码
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String header;
/**
* 性别
*/
private Integer gender;
/**
* 生日
*/
private Date birth;
/**
* 所在城市
*/
private String city;
/**
* 职业
*/
private String job;
/**
* 个性签名
*/
private String sign;
/**
* 用户来源
*/
private Integer sourceType;
/**
* 积分
*/
private Integer integration;
/**
* 成长值
*/
private Integer growth;
/**
* 启用状态
*/
private Integer status;
/**
* 注册时间
*/
private Date createTime;
/**
* accesstoken码
*/
private String accessToken;
/**
* 过期时间
*/
private long expiresIn;
/**
* 社区账户的id
*/
private String socialUid;
}
@Data
@TableName("ums_member")
public class MemberEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId
private Long id;
/**
* 会员等级id
*/
private Long levelId;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 昵称
*/
private String nickname;
/**
* 手机号码
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String header;
/**
* 性别
*/
private Integer gender;
/**
* 生日
*/
private Date birth;
/**
* 所在城市
*/
private String city;
/**
* 职业
*/
private String job;
/**
* 个性签名
*/
private String sign;
/**
* 用户来源
*/
private Integer sourceType;
/**
* 积分
*/
private Integer integration;
/**
* 成长值
*/
private Integer growth;
/**
* 启用状态
*/
private Integer status;
/**
* 注册时间
*/
private Date createTime;
/**
* accesstoken码
*/
private String accessToken;
/**
* 过期时间
*/
private long expiresIn;
/**
* 社区账户的id
*/
private String socialUid;
}