一、參考文檔
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;
}