科普网站建设方案,办公室现代简约装修,湘潭县建设投资有限公司网站,软文发稿网站开发之前 需求#xff1a;网站接入qq,sina微博登录#xff0c;本文最后付效果图#xff1a; 说明#xff1a;大部分网站本身是需要用户概念的#xff0c;很多操作依附于用户#xff0c;而qq或微博作为一种登录方式指向用户而已#xff0c;我参考了一下其他网站的做法网站接入qq,sina微博登录本文最后付效果图 说明大部分网站本身是需要用户概念的很多操作依附于用户而qq或微博作为一种登录方式指向用户而已我参考了一下其他网站的做法 一般有如下两种做法 1强制绑定用户第一次通过qq登录时必须与该网站账户绑定也就是用户必须要先有一个此网站账户才能登录成功 2互相独立用户第一次通过qq登录时直接重新为用户注册一个账户如以用户名为qq_123456直接注册一个账户与其他账户无关 站在用户角度考虑下可能需要更多的选择性因此我是如下考虑的: 用户登录后在个人中心中也可设置绑定。 --------------------------------------------------------------------------------------------------- 文档说明 现在大部分第三方的登录OAuth2.0为标准所以开发流程基本都一致一般都是一下步骤 1申请接入获取appidappkey接入后又第三方发放 2用户登录第三方下发token 3通过token获取用户唯一标示一般是一个openId api地址 qq:http://wiki.connect.qq.com/api列表 sinahttp://open.weibo.com/wiki/授权机制 qqsina也提供了java sdk https://github.com/sunxiaowei2014/weibo4j-oauth2-beta3.1.1/ http://qzonestyle.gtimg.cn/qzone/vas/opensns/res/doc/qqConnect_Server_SDK_java_v2.0.zip sina的虽然开源了但里面很多代码写的有问题用的之后需要注意 ------------------------------------------------------------------------------------------------------------ 开发 数据结构方面需要加以一张表用来维护登录方式和用户关联通过openId以及登录方式确定唯一性 网站引入appid,appkey,回调地址的配置有不再赘述了 代码基本上参照sdk中的demo就可以了 简单贴一下controllerspringMVC架构中的代码吧 AUthController为父类存放一些第三方登录的通用方法BindController为用户绑定提供方法第三方登录的controller基本上就是一个登录跳转方法一个回调方法以及一些接口api的调用 public abstract class AuthController extends BaseController {Resourceprivate JavaMailSender mailSender;Resourceprivate IBAuthService authService;protected LoginUser getU(BAuth auth){LoginUser loginUser new LoginUser();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());return loginUser;}protected LoginUser getU(User user){LoginUser loginUser new LoginUser();loginUser.setIcon(user.getIcon() null ? IPortalConstants.defaultIconUrl: user.getIcon());loginUser.setId(user.getId());loginUser.setLoginType(AuthType.bresume.getCode());loginUser.setNickName( user.getNickName());return loginUser;}protected boolean setUser2Session(BAuth auth){LoginUser loginuser this.getU(auth);SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;}protected boolean setUser2Session(User user){LoginUser loginuser this.getU(user);SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;}protected void sendRegisterMail(User user,String code) {PropertiesLoader loader new PropertiesLoader(mail.properties);MapString, Object map new HashMapString, Object();Email email new Email();email.setSender(loader.getProperty(mail.from));email.setAddress(user.getEmail());email.setSubject(loader.getProperty(mail.register.success.subject));// 从模板生成HashMapString, Object param new HashMapString, Object();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);}protected String callBack(Model model,BAuth newAuth){BAuth oldAuth authService.findOne(newAuth.getOpenId(),newAuth.getType());if (oldAuth ! null oldAuth.getUser() ! null) {// 判定有登录记录//刷新accessTokenoldAuth.setAccessToken(newAuth.getAccessToken());oldAuth.setExpiresIn(newAuth.getExpiresIn());oldAuth.setIcon(newAuth.getIcon());oldAuth.setNickName(newAuth.getNickName());oldAuth.setRefreshAccessTime(new Date());authService.update(oldAuth);this.setUser2Session(oldAuth);return redirect:/index;} else if(oldAuthnull) {// 判定首次登录记录oldAuth new BAuth();oldAuth.setAccessToken(newAuth.getAccessToken());oldAuth.setExpiresIn(newAuth.getExpiresIn());oldAuth.setCreatedTime(new Date());oldAuth.setIcon(newAuth.getIcon());oldAuth.setNickName(newAuth.getNickName());oldAuth.setOpenId(newAuth.getOpenId());oldAuth.setRefreshAccessTime(new Date());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(new Date());authService.update(oldAuth);//用户绑定,跳转页面model.addAttribute(openId, newAuth.getOpenId());model.addAttribute(loginFrom, newAuth.getType());return site/bindAuth.jsp;}}} AuthController RequestMapping(/)
Controller
public class BindController extends AuthController {Resourceprivate IUserService userService;Resourceprivate IBAuthService authService;Resourceprivate IUserVerifiedService verifiedService;Resourceprivate JavaMailSender mailSender;RequestMapping(/ingore-bind)public String 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 new User();/** 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 usernew User();
// 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 new UserVerified(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(/)
Controller
public class QQController extends AuthController {Resourceprivate IBAuthService authService;Resourceprivate IUserService userService;RequestMapping(/qqlogin)public void index(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType(text/html;charsetutf-8);try {response.sendRedirect(new Oauth().getAuthorizeURL(request));LOGGER.info(login by qq);} catch (QQConnectException e) {e.printStackTrace();}}RequestMapping(/qq_callback)public String callback(HttpServletRequest request,HttpServletResponse response, Model model) {try {AccessToken accessTokenObj (new Oauth()).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 去获取当前用的openidOpenID openIDObj new OpenID(accessToken);openID openIDObj.getUserOpenID();LOGGER.info(利用获取到的accessToken: accessToken , 去获取到当前用户openid: openID .);String icon null, nickName null;// 去获取用户在Qzone的昵称等信息UserInfo qzoneUserInfo new UserInfo(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 new BAuth();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) {// 判定有登录记录//刷新accessTokenbauth.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(bauthnull) {// 判定首次登录记录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 void talk(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType(text/html;charsetutf-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 new Topic(accessToken, openID);try {GeneralResultBean grb topic.addTopic(con);if (grb.getRet() 0) {response.getWriter().println(a href\http://www.qzone.com\ target\_blank\您的说说已发表成功请登录Qzone查看/a);} else {response.getWriter().println(很遗憾的通知您发表说说失败原因 grb.getMsg());}} catch (QQConnectException e) {System.out.println(抛异常了);}} else {System.out.println(获取到的值为空);}}
} QQController RequestMapping(/)
Controller
public class SinaController extends AuthController {Resourceprivate IBAuthService authService;Resourceprivate IUserService userService;RequestMapping(/sinalogin)public void index(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType(text/html;charsetutf-8);try {response.sendRedirect(new Oauth().authorize(code));LOGGER.info(login by weibo);} catch (WeiboException e) {e.printStackTrace();}}RequestMapping(/weibo_callback)public String callback(HttpServletRequest request,HttpServletResponse response, Model model) throws IOException {try {Oauth oauth new Oauth();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 new Users(accessToken);User user um.showUserById(openId);LOGGER.info(user.toString());BAuth newAuth new BAuth();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用户登录后可在个人设置中管理第三方登录的绑定 转载于:https://www.cnblogs.com/china2k/p/4217108.html