开发之前

需求:网站接入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相关推荐

  1. 第三方支付接口 个人第三方支付接口 第三方支付接口费率

    第三方支付接口 个人第三方支付接口 第三方支付接口费率 支付扫码是现在很多人日常都会有的一个行为,不管是去超市.饭店还是其他地方消费的话都会打开微信扫描商家提供的收款码.不过有很多商家和消费者就发现微 ...

  2. php新浪微博第三方登录接口,手机第三方新浪微博登录php api实现分析

    提供api,POST方式,根据传递过来的微博uid/appkey,判断该用户的ID是否在自己的数据库中. 如果有,直接登录返回用户登录api的json. 如果没有,就将该用户的ID+token请求微博 ...

  3. python 登录接口_使用python编写一个登录接口

    需求: 编写登录接口 输入用户名密码 认证成功后 显示欢迎信息 输入三次后锁定 用户信息文件 黑名单的文件 黑名单里检查,不让登录 用户名密码判定 流程图: 代码:#!/usr/bin/env pyt ...

  4. python编写登录接口_使用python编写一个登录接口

    需求: 编写登录接口 输入用户名密码 认证成功后 显示欢迎信息 输入三次后锁定 用户信息文件 黑名单的文件 黑名单里检查,不让登录 用户名密码判定 流程图: 代码:#!/usr/bin/env pyt ...

  5. java 登录下线_单机登录实现思路(强制下线其他用户)

    主流的网站都是限制用户单点登录的,为什么要实现单点登录? 1.避免单账号多用户操作占用大量数据库连接,减轻webserver的压力: 2.安全防范,强制下线非法用户: 传统的web服务器(如tomca ...

  6. python用户名密码登录退出_用户登录登出

    一.功能需求分析 1.登录功能分析 1.1登录流程 1.2功能(一个请求为一个功能) -登录页面 -登录功能 -登出功能 二.登录页面 1.接口设计 1.1.接口说明 类目 说明 请求方式 GET u ...

  7. 微信登录画面_微信登录界面的地球变了_微信登录界面首变真相

    细心的小伙伴发现在启动微信的时候,那个经典的一个小人剪影面对着地球的画面开始发生了一些变化,似乎云层变得更为清晰细致了.微信登录界面6年来首变化,那么为何改变来的如此突然呢,下面小编就分享给大家! 手 ...

  8. java调用easyxml接口_【技术教程】如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口?...

    原标题:[技术教程]如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口? RTSP协议视频平台EasyNVR经过多年的积累,已经是一套成熟且完善的视频平台了,用户可以通过网页直接访 ...

  9. java自动推断类型_推断:Facebook的新Java静态分析工具

    java自动推断类型 如何使用Facebook的Infer改善Java开发工作流程? 如果您与技术话题保持同步(如果您正在阅读此博客,我想您会这样做),那么您可能听说过Facebook 刚刚向公众发布 ...

最新文章

  1. MySQL-事务管理(基础)
  2. 软件项目开发之 软件过程RUP初探
  3. 排序算法复习—希尔排序
  4. vue 使用 better-scroll
  5. 遥感影像单波段辐射定标处理
  6. 在 Cloudera Data Flow 上运行你的第一个 Flink 例子
  7. 软件工程导论复习知识点
  8. IOS 10.3.3 Meridian越狱
  9. 英语基础语法(五)-形容词、副词
  10. HTK安装实录(Ubuntu18.04)
  11. 金蝶中间层服务器组件注册使用信任方式,提示:用户名或密码错误
  12. imwrite()和imshow()相关
  13. mac无法安装dmg文件,报无可装载系统错误
  14. FZU 1573 大学自习室
  15. html背景音乐教程pdf,HTML插入背景音乐方法【全】
  16. (Python)视频生成器
  17. 设计分享|基于单片机的矩阵电子琴(汇编)
  18. 20200205 打印沙漏
  19. 漫谈Web Feed、RSS、原文链接和转贴
  20. 全同态加密(FHE)设计思路

热门文章

  1. NAT、远程访问和站点间***集成
  2. W-Cms XSS和遍历目录漏洞
  3. PythonTips1
  4. Communication System--ZOJ 1409
  5. vhdl变量赋初值_变量类型、构造器、封装以及 LeetCode 每日一题
  6. angular获取路由参数_Angular应用带参数的路由实现
  7. php java memcached_php-memcached详解
  8. 认真学习系列:编译原理——B站笔记
  9. MacOS使用top命令查看进程使用内存
  10. 思路不清晰还想月薪过万?学会这4招,升职加薪有望