java第三方登录接口_第三方登录接入-qq,weibo-java
开发之前
需求:网站接入qq,sina微博登录,本文最后付效果图:
说明:大部分网站本身是需要用户概念的,很多操作依附于用户,而qq或微博作为一种登录方式指向用户而已,我参考了一下其他网站的做法,
一般有如下两种做法:
1,强制绑定:用户第一次通过qq登录时必须与该网站账户绑定,也就是用户必须要先有一个此网站账户才能登录成功
2,互相独立,用户第一次通过qq登录时直接重新为用户注册一个账户,如以用户名为qq_123456直接注册一个账户,与其他账户无关;
站在用户角度考虑下,可能需要更多的选择性,因此我是如下考虑的:
用户登录后在个人中心中也可设置绑定。
---------------------------------------------------------------------------------------------------
文档说明
现在大部分第三方的登录OAuth2.0为标准,所以开发流程基本都一致,一般都是一下步骤:
1,申请接入,获取appid&appkey(接入后又第三方发放)
2,用户登录第三方下发token,
3,通过token获取用户唯一标示,一般是一个openId
api地址:
qq&sina也提供了java sdk
sina的虽然开源了,但里面很多代码写的有问题,用的之后需要注意
------------------------------------------------------------------------------------------------------------
开发
数据结构方面需要加以一张表用来维护登录方式和用户关联(通过openId以及登录方式确定唯一性)
网站引入,appid,appkey,回调地址的配置有不再赘述了
代码基本上参照sdk中的demo就可以了,
简单贴一下controller(springMVC架构)中的代码吧
AUthController为父类,存放一些第三方登录的通用方法,BindController为用户绑定提供方法,第三方登录的controller基本上就是一个登录跳转方法,一个回调方法,以及一些接口api的调用
public abstract class AuthController extendsBaseController {
@ResourceprivateJavaMailSender mailSender;
@ResourceprivateIBAuthService authService;protectedLoginUser getU(BAuth auth){
LoginUser loginUser= newLoginUser();
loginUser.setAccessToken(auth.getAccessToken());
loginUser
.setIcon(auth.getIcon()== null ?IPortalConstants.defaultIconUrl
: auth.getIcon());
loginUser.setId(auth.getUser().getId());
loginUser.setLoginType(auth.getType());
loginUser.setNickName(auth.getNickName()== null ?auth.getUser()
.getNickName() : auth.getNickName());
loginUser.setOpenId(auth.getOpenId());returnloginUser;
}protectedLoginUser getU(User user){
LoginUser loginUser= newLoginUser();
loginUser
.setIcon(user.getIcon()== null ?IPortalConstants.defaultIconUrl
: user.getIcon());
loginUser.setId(user.getId());
loginUser.setLoginType(AuthType.bresume.getCode());
loginUser.setNickName( user.getNickName());returnloginUser;
}protected booleansetUser2Session(BAuth auth){
LoginUser loginuser= this.getU(auth);
SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;
}protected booleansetUser2Session(User user){
LoginUser loginuser= this.getU(user);
SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;
}protected voidsendRegisterMail(User user,String code) {
PropertiesLoader loader= new PropertiesLoader("mail.properties");
Map map = new HashMap();
Email email= newEmail();
email.setSender(loader.getProperty("mail.from"));
email.setAddress(user.getEmail());
email.setSubject(loader.getProperty("mail.register.success.subject"));//从模板生成
HashMap param = new HashMap();
param.put("userName", user.getUserName());
param.put("userId", user.getId());
param.put("code", code);
email.setContent(MailUtils.getMailText(param,
loader.getProperty("mail.register.success.content")));
map.put("email", email);
MailUtils.sendMailByAsynchronousMode(map, mailSender);
}protectedString callBack(Model model,BAuth newAuth){
BAuth oldAuth=authService.findOne(newAuth.getOpenId(),newAuth.getType());if (oldAuth != null && oldAuth.getUser() != null) {//判定有登录记录//刷新accessToken
oldAuth.setAccessToken(newAuth.getAccessToken());
oldAuth.setExpiresIn(newAuth.getExpiresIn());
oldAuth.setIcon(newAuth.getIcon());
oldAuth.setNickName(newAuth.getNickName());
oldAuth.setRefreshAccessTime(newDate());
authService.update(oldAuth);this.setUser2Session(oldAuth);return "redirect:/index";
}else if(oldAuth==null) {//判定首次登录,记录
oldAuth = newBAuth();
oldAuth.setAccessToken(newAuth.getAccessToken());
oldAuth.setExpiresIn(newAuth.getExpiresIn());
oldAuth.setCreatedTime(newDate());
oldAuth.setIcon(newAuth.getIcon());
oldAuth.setNickName(newAuth.getNickName());
oldAuth.setOpenId(newAuth.getOpenId());
oldAuth.setRefreshAccessTime(newDate());
oldAuth.setType(newAuth.getType());
authService.save(oldAuth);//用户绑定,跳转页面
model.addAttribute("openId", newAuth.getOpenId());
model.addAttribute("loginFrom", newAuth.getType());return "site/bindAuth.jsp";
}else{//登录过但因某种原因为绑定账户
oldAuth.setAccessToken(newAuth.getAccessToken());
oldAuth.setExpiresIn(newAuth.getExpiresIn());
oldAuth.setIcon(newAuth.getIcon());
oldAuth.setNickName(newAuth.getNickName());
oldAuth.setRefreshAccessTime(newDate());
authService.update(oldAuth);//用户绑定,跳转页面
model.addAttribute("openId", newAuth.getOpenId());
model.addAttribute("loginFrom", newAuth.getType());return "site/bindAuth.jsp";
}
}
}
AuthController
@RequestMapping("/")
@Controllerpublic class BindController extendsAuthController {
@ResourceprivateIUserService userService;
@ResourceprivateIBAuthService authService;
@ResourceprivateIUserVerifiedService verifiedService;
@ResourceprivateJavaMailSender mailSender;
@RequestMapping("/ingore-bind")publicString ingore_bind(
@RequestParam(value= "loginFrom", required = true) Integer loginFrom,
@RequestParam(value= "openId", required = true) String openId,
ModelMap model, HttpServletResponse response) {
BAuth auth=authService.findOne(openId, loginFrom);if (auth == null) {return "404";
}if (auth.getUser() == null) {
User user= newUser();/** user.setUserName(userName); user.setPassword(password);*/
//user.setEmail(email);
user.setNickName(auth.getNickName());
user.setIcon(auth.getIcon());
user.setRegisterType(AuthType.fromCode(loginFrom).getRt().getType());
user.setType(UserType.PERSIONAL.getCode());
user.setLevel(0);
userService.registerFromAuth(user);
auth.setUser(user);
authService.save(auth);
}this.setUser2Session(auth);return "redirect:/index";
}
@RequestMapping("/login-bind")public@ResponseBody JSONObject bind(
@RequestParam(value= "loginFrom", required = true) Integer loginFrom,
@RequestParam(value= "openId", required = true) String openId,
@RequestParam(value= "email", required = true) String email,
@RequestParam(value= "password", required = true) String password,
ModelMap model, HttpServletResponse response) {
BAuth auth=authService.findOne(openId, loginFrom);if (auth == null) {return this.toJSONResult(false,"404");
}if (auth.getUser() == null) {try{//登陆校验
User user =userService.loginCheck(email, password);
auth.setUser(user);
authService.update(auth);
}catch(CoreException e) {if (e.getErrorCode() ==PortalErrorCode.USER_PASSWORD_ERROR_TIMES_EXCEED_ERROR) {return this.toJSONResult(false,this.getMessage(e, e.getArgs()));
}else{return this.toJSONResult(false, this.getMessage(e));
}
}
}this.setUser2Session(auth);return this.toJSONResult(true);
}
@RequestMapping("/regist-bind")public@ResponseBody JSONObject registBind(
@RequestParam(value= "loginFrom", required = true) Integer loginFrom,
@RequestParam(value= "openId", required = true) String openId,
@RequestParam(value= "email", required = true) String email,
@RequestParam(value= "password", required = true) String password,
ModelMap model, HttpServletResponse response) {
BAuth auth=authService.findOne(openId, loginFrom);if (auth == null) {return this.toJSONResult(false);
}if (auth.getUser() == null) {
User user=newUser();//user.setUserName(userName);
user.setPassword(password);
user.setEmail(email);try{
user.setRegisterType(RegisterType.PORTAL_REGISTER.getType());
user.setType(UserType.PERSIONAL.getCode());
user.setLevel(0);
user.setNickName(auth.getNickName());
user.setIcon(auth.getIcon());
userService.register(user);//生成邮箱验证码
UserVerified uv = newUserVerified(user);
verifiedService.save(uv);//发送注册成功的邮件
if(CommonUtils.isNotEmpty(user.getEmail())) {
sendRegisterMail(user,uv.getCode());
}
}catch(CoreException e) {return this.toJSONResult(false, this.getMessage(e));
}
auth.setUser(user);
authService.save(auth);
}this.setUser2Session(auth);return this.toJSONResult(true);
}
}
BindController
@RequestMapping("/")
@Controllerpublic class QQController extendsAuthController {
@ResourceprivateIBAuthService authService;
@ResourceprivateIUserService userService;
@RequestMapping("/qqlogin")public voidindex(HttpServletRequest request, HttpServletResponse response,
Model model)throwsIOException {
response.setContentType("text/html;charset=utf-8");try{
response.sendRedirect(newOauth().getAuthorizeURL(request));
LOGGER.info("login by qq");
}catch(QQConnectException e) {
e.printStackTrace();
}
}
@RequestMapping("/qq_callback")publicString callback(HttpServletRequest request,
HttpServletResponse response, Model model) {try{
AccessToken accessTokenObj= (newOauth())
.getAccessTokenByRequest(request);
String accessToken= null, openID = null;long tokenExpireIn = 0L;if (accessTokenObj.getAccessToken().equals("")) {
LOGGER.error("QQ Login failed,caused by 没有获取到响应参数");return "404";
}
accessToken=accessTokenObj.getAccessToken();
tokenExpireIn=accessTokenObj.getExpireIn();
LOGGER.info("Get accessToken from qq,accessToken:" +accessToken+ ",tokenExpireIn" +tokenExpireIn);//利用获取到的accessToken 去获取当前用的openid
OpenID openIDObj = newOpenID(accessToken);
openID=openIDObj.getUserOpenID();
LOGGER.info("利用获取到的accessToken:" +accessToken+ ", 去获取到当前用户openid:" + openID + ".");
String icon= null, nickName = null;//去获取用户在Qzone的昵称等信息
UserInfo qzoneUserInfo = newUserInfo(accessToken, openID);
UserInfoBean userInfoBean=qzoneUserInfo.getUserInfo();if (userInfoBean.getRet() == 0) {
nickName=userInfoBean.getNickname();//userInfoBean.getGender();
icon=userInfoBean.getAvatar().getAvatarURL30();//userInfoBean.getAvatar().getAvatarURL50();//userInfoBean.getAvatar().getAvatarURL100();
} else{
LOGGER.error("很抱歉,我们没能正确获取到您的信息,原因是:" +userInfoBean.getMsg());
}
BAuth newAuth= newBAuth();
newAuth.setAccessToken(accessToken);
newAuth.setExpiresIn(tokenExpireIn);
newAuth.setIcon(icon);
newAuth.setNickName(nickName);
newAuth.setOpenId(openID);
newAuth.setType(AuthType.QQ.getCode());return this.callBack(model, newAuth);//通过openid判断首次登录与否
/*BAuth bauth = authService.findOne(openID, AuthType.QQ.getCode());
if (bauth != null && bauth.getUser() != null) {
// 判定有登录记录
//刷新accessToken
bauth.setAccessToken(accessToken);
bauth.setExpiresIn(tokenExpireIn);
bauth.setIcon(icon);
bauth.setNickName(nickName);
bauth.setRefreshAccessTime(new Date());
authService.update(bauth);
this.setUser2Session(bauth);
return "redirect:/index";
} else if(bauth==null) {
// 判定首次登录,记录
bauth = new BAuth();
bauth.setAccessToken(accessToken);
bauth.setCreatedTime(new Date());
bauth.setExpiresIn(tokenExpireIn);
bauth.setIcon(icon);
bauth.setNickName(nickName);
bauth.setOpenId(openID);
bauth.setRefreshAccessTime(new Date());
bauth.setType(AuthType.QQ.getCode());
authService.save(bauth);
//用户绑定,跳转页面
model.addAttribute("openId", openID);
model.addAttribute("loginFrom", AuthType.QQ.getCode());
return "site/bindAuth.jsp";
}else{
// 登录过但因某种原因为绑定账户
bauth.setAccessToken(accessToken);
bauth.setExpiresIn(tokenExpireIn);
bauth.setIcon(icon);
bauth.setNickName(nickName);
bauth.setRefreshAccessTime(new Date());
authService.update(bauth);
//用户绑定,跳转页面
model.addAttribute("openId", openID);
model.addAttribute("loginFrom", AuthType.QQ.getCode());
return "site/bindAuth.jsp";
}*/}catch(QQConnectException e) {
e.printStackTrace();
}return "redirect:/index";
}
@RequestMapping("/qqss")public voidtalk(HttpServletRequest request, HttpServletResponse response,
Model model)throwsIOException {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
String con= request.getParameter("con");
HttpSession session=request.getSession();
String accessToken= (String) session.getAttribute("demo_access_token");
String openID= (String) session.getAttribute("demo_openid");
System.out.println(accessToken);
System.out.println(openID);//请开发者自行校验获取的con值是否有效
if (con != "") {
Topic topic= newTopic(accessToken, openID);try{
GeneralResultBean grb=topic.addTopic(con);if (grb.getRet() == 0) {
response.getWriter()
.println("您的说说已发表成功,请登录Qzone查看");
}else{
response.getWriter().println("很遗憾的通知您,发表说说失败!原因: " +grb.getMsg());
}
}catch(QQConnectException e) {
System.out.println("抛异常了?");
}
}else{
System.out.println("获取到的值为空?");
}
}
}
QQController
@RequestMapping("/")
@Controllerpublic class SinaController extendsAuthController {
@ResourceprivateIBAuthService authService;
@ResourceprivateIUserService userService;
@RequestMapping("/sinalogin")public voidindex(HttpServletRequest request, HttpServletResponse response,
Model model)throwsIOException {
response.setContentType("text/html;charset=utf-8");try{
response.sendRedirect(new Oauth().authorize("code"));
LOGGER.info("login by weibo");
}catch(WeiboException e) {
e.printStackTrace();
}
}
@RequestMapping("/weibo_callback")publicString callback(HttpServletRequest request,
HttpServletResponse response, Model model)throwsIOException {try{
Oauth oauth= newOauth();
String code= request.getParameter("code");
LOGGER.info("code: " +code);
AccessToken accessTokenObj=oauth.getAccessTokenByCode(code);if (accessTokenObj == null) {
LOGGER.error("AccessToken 获取失败,code:" +code);
}
String accessToken=accessTokenObj.getAccessToken();
String openId=accessTokenObj.getUID();
String expireInStr=accessTokenObj.getExpireIn();
Users um= newUsers(accessToken);
User user=um.showUserById(openId);
LOGGER.info(user.toString());
BAuth newAuth= newBAuth();
newAuth.setAccessToken(accessToken);
newAuth.setExpiresIn(expireInStr!= null ?Long
.parseLong(expireInStr) :3600);
newAuth.setIcon(user.getAvatarLarge());
newAuth.setNickName(user.getScreenName());
newAuth.setOpenId(openId);
newAuth.setType(AuthType.SINA.getCode());return this.callBack(model, newAuth);
}catch(WeiboException e) {if (401 ==e.getStatusCode()) {
LOGGER.error("Unable to get the access token.");
}else{
e.printStackTrace();
}
}return "redirect:/index";
}
}
SinaController
-------------------------------------------------------------------------------------------------------------
页面效果
注:该流程为用户首次使用第三方登录时流程
1,登录页面放置第三方登录图标
2,点击图标接入第三方接口,可跳转至第三方登录界面
3,第三方登录完成,用户账户绑定
4,用户登录后,可在个人设置中管理第三方登录的绑定
java第三方登录接口_第三方登录接入-qq,weibo-java相关推荐
- 第三方支付接口 个人第三方支付接口 第三方支付接口费率
第三方支付接口 个人第三方支付接口 第三方支付接口费率 支付扫码是现在很多人日常都会有的一个行为,不管是去超市.饭店还是其他地方消费的话都会打开微信扫描商家提供的收款码.不过有很多商家和消费者就发现微 ...
- php新浪微博第三方登录接口,手机第三方新浪微博登录php api实现分析
提供api,POST方式,根据传递过来的微博uid/appkey,判断该用户的ID是否在自己的数据库中. 如果有,直接登录返回用户登录api的json. 如果没有,就将该用户的ID+token请求微博 ...
- python 登录接口_使用python编写一个登录接口
需求: 编写登录接口 输入用户名密码 认证成功后 显示欢迎信息 输入三次后锁定 用户信息文件 黑名单的文件 黑名单里检查,不让登录 用户名密码判定 流程图: 代码:#!/usr/bin/env pyt ...
- python编写登录接口_使用python编写一个登录接口
需求: 编写登录接口 输入用户名密码 认证成功后 显示欢迎信息 输入三次后锁定 用户信息文件 黑名单的文件 黑名单里检查,不让登录 用户名密码判定 流程图: 代码:#!/usr/bin/env pyt ...
- java 登录下线_单机登录实现思路(强制下线其他用户)
主流的网站都是限制用户单点登录的,为什么要实现单点登录? 1.避免单账号多用户操作占用大量数据库连接,减轻webserver的压力: 2.安全防范,强制下线非法用户: 传统的web服务器(如tomca ...
- python用户名密码登录退出_用户登录登出
一.功能需求分析 1.登录功能分析 1.1登录流程 1.2功能(一个请求为一个功能) -登录页面 -登录功能 -登出功能 二.登录页面 1.接口设计 1.1.接口说明 类目 说明 请求方式 GET u ...
- 微信登录画面_微信登录界面的地球变了_微信登录界面首变真相
细心的小伙伴发现在启动微信的时候,那个经典的一个小人剪影面对着地球的画面开始发生了一些变化,似乎云层变得更为清晰细致了.微信登录界面6年来首变化,那么为何改变来的如此突然呢,下面小编就分享给大家! 手 ...
- java调用easyxml接口_【技术教程】如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口?...
原标题:[技术教程]如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口? RTSP协议视频平台EasyNVR经过多年的积累,已经是一套成熟且完善的视频平台了,用户可以通过网页直接访 ...
- java自动推断类型_推断:Facebook的新Java静态分析工具
java自动推断类型 如何使用Facebook的Infer改善Java开发工作流程? 如果您与技术话题保持同步(如果您正在阅读此博客,我想您会这样做),那么您可能听说过Facebook 刚刚向公众发布 ...
最新文章
- MySQL-事务管理(基础)
- 软件项目开发之 软件过程RUP初探
- 排序算法复习—希尔排序
- vue 使用 better-scroll
- 遥感影像单波段辐射定标处理
- 在 Cloudera Data Flow 上运行你的第一个 Flink 例子
- 软件工程导论复习知识点
- IOS 10.3.3 Meridian越狱
- 英语基础语法(五)-形容词、副词
- HTK安装实录(Ubuntu18.04)
- 金蝶中间层服务器组件注册使用信任方式,提示:用户名或密码错误
- imwrite()和imshow()相关
- mac无法安装dmg文件,报无可装载系统错误
- FZU 1573 大学自习室
- html背景音乐教程pdf,HTML插入背景音乐方法【全】
- (Python)视频生成器
- 设计分享|基于单片机的矩阵电子琴(汇编)
- 20200205 打印沙漏
- 漫谈Web Feed、RSS、原文链接和转贴
- 全同态加密(FHE)设计思路