个人博客系统开发总结之 第三方登录(QQ、微博)

        当别人访问我的博客系统时,如果需要评论,就需要登录。如果此时要求注册,就比较麻烦,并且会引起访问者的反感。于是就采用第三方登录。目前支持QQ、微博登录。

QQ登录

        QQ互联开放平台为第三方网站提供了丰富的API。第三方网站接入QQ互联开放平台后,即可通过调用平台提供的API实现用户使用QQ帐号登录网站功能,且可以获取到腾讯QQ用户的相关信息。

1、认证成为开发者

         要使用腾讯提供的QQ登录API,就必须在QQ互联管理中心新建应用以获取应用的APPID 和 APP KEY,新建应用之前需要认证成为开发者,否则应用无法提交审核。认证成为开发者就是提供一些个人资料,比如联系方式,身份证号,身份证照片等,提交腾讯审核,审核通过即可成为开发者。

 2、新建网站应用

        点击上图中创建应用按钮,进行创建应用。填写应用信息,包括网站名称、类别、简介、网站地址、网站回调地址、网站备案号等。网站回调地址即用户授权QQ登录后的回调地址。新建的网站应用需通过审核才能让其他人使用QQ登录功能,如果审核未通过,只有网站所有者能使用QQ登录功能。

微博登录

      微博登录的准备工作同QQ登录的准备工作,在微博开放平台上注册成为开发者,创建应用,提交审核等。

3、网站中添加QQ登录、微博登录功能

扫描二维码关注公众号,回复: 4472366 查看本文章

        (1)网站中添加QQ、微博登录标识

<span data-platform-id="3" class="login-logo" title="QQ登录" 
    onclick="oRegisterBtn.loginQQ()">
	<i class="layui-icon" style="font-size: 40px; color: #1E9FFF;">&#xe676;</i>
</span>
<span data-platform-id="3" class="login-logo" title="微博登录"     
    onclick="oRegisterBtn.weiboLogin()">
	<i class="layui-icon" style="font-size: 40px; color: #EE2C2C;">&#xe675;</i>
</span>

         (2)loginQQ、weiboLogin

/**
 * 第三方QQ登录
 */
 loginQQ: function() {
	 let clientId = '101528188';
	 let redirect_uri = 'http://22815l1b14.iask.in/thirdLogin/qqLogin';
	 let state = '123456789';
	 window.open(`https://graph.qq.com/oauth2.0/authorize?        
 client_id=${clientId}&response_type=code&redirect_uri=${encodeURIComponent(redirect_uri)}&state=${state}`);
},
/**
 * 微博登录
 */
 weiboLogin: function(){
	 let weiboAppId = '2191145838';
	 let weiboAuthPath = 'http://22815l1b14.iask.in/thirdLogin/weiboLogin';
	 window.open(`https://api.weibo.com/oauth2/authorize?client_id=${weiboAppId}&response_type=code&redirect_uri=${encodeURIComponent(weiboAuthPath)}`);
},

      (3)QQ、微博登录成功后回调处理

QQ登录步骤如下:户成功登录并授权,则会跳转到指定的回调地址,并在回调地址后面带上code值——>通过code获取access token——>通过acess token获取openId——>通过openId获取QQ信息(昵称、头像、性别等)

微博登录步骤如下:户成功登录并授权,则会跳转到指定的回调地址,并在回调地址后面带上code值——>通过code获取access token和uid——>通过acess token和uid获取微博信息(昵称、头像、性别等)

具体步骤腾讯、微博开放平台上有详细步骤,不再赘述。详见腾讯开放平台接入文档微博开放平台文档

/**
 * 
 * @ClassName::ThirdPartyLoginController @Description: 第三方登录控制器
 * @author :柯雷
 * @date :2018年11月29日 下午1:51:45
 *
 */
@Controller
@RequestMapping("/thirdLogin")
public class ThirdPartyLoginController {

	/** 微博第三方登录信息 */
	private static final String APP_KEY_WEIBO = "2191145838";
	private static final String APP_SECRECT_WEIBO = "e8066160a6a5ab6afa7775147993465e";
	private static final String REDIRECT_URI_WEIBO = "http://22815l1b14.iask.in/thirdLogin/weiboLogin";

	/** QQ第三方登录信息 */
	private static final String APP_KEY_QQ = "101528188";
	private static final String APP_SECRECT_QQ = "7975cb8105e679e90e87d02c297dbb6a";
	private static final String REDIRECT_URI_QQ = "http://22815l1b14.iask.in/thirdLogin/qqLogin";

	/**
	 * @Description 用户处理对象
	 */
	@Autowired
	UserService userServiceImpl;

	/**
	 * 日志打印对象
	 */
	private static final Logger logger = LoggerFactory.getLogger(ThirdPartyLoginController.class);

	/**
	 * @throws
	 * UnsupportedEncodingException @Title:qqLogin @Description:qq登录成功回调函数 @param
	 * :@return @return :String @throws
	 */
	@RequestMapping("/qqLogin")
	@ResponseBody
	public String qqLoginCallBack(HttpServletRequest request, Model model) throws UnsupportedEncodingException {
		logger.info("【ThirdPartyLoginController.qqLoginCallBack】QQ登录成功回调函数");
		// 返回参数
		Map<String, Object> rtnMap = new HashMap<>();
		// 1、用户登录成功并授权后跳转到回调地址待的参数code
		String code = request.getParameter("code");

		try {
			Map<String, Object> params = new HashMap<>();
			params.put("client_id", APP_KEY_QQ);
			params.put("client_secret", APP_SECRECT_QQ);
			params.put("grant_type", "authorization_code");
			params.put("code", code);
			params.put("redirect_uri", REDIRECT_URI_QQ);

			// 2、通过code值获取access token
			String auth_token = "{\"" + HttpRequestUtil.doGet("https://graph.qq.com/oauth2.0/token", params)
					.replaceAll("&", "\",\"").replaceAll("=", "\":\"") + "\"}";
			Map<String, Object> authMap = JSONObject.parseObject(auth_token);

			Integer errorCode = (Integer) authMap.get("code");
			String errorMsg = (String) authMap.get("msg");
			if (errorCode != null && errorCode != 0) {
				throw new Exception(errorMsg);
			}

			String access_token = (String) authMap.get("access_token");

			// 3、根据access token获取openID
			String open_id = HttpRequestUtil.doGet("https://graph.qq.com/oauth2.0/me?access_token=" + access_token);
			open_id = open_id.substring(10, open_id.length() - 2);

			Map<String, Object> operidMap = JSONObject.parseObject(open_id);

			errorCode = (Integer) operidMap.get("code");
			errorMsg = (String) operidMap.get("msg");
			if (errorCode != null && errorCode != 0) {
				throw new Exception(errorMsg);
			}

			String openid = (String) operidMap.get("openid");

			// 4、根据access token和openid获取QQ信息
			String user = HttpRequestUtil.doGet("https://graph.qq.com/user/get_user_info?access_token=" + access_token
					+ "&oauth_consumer_key=" + APP_KEY_QQ + "&openid=" + openid);

			Map<String, Object> qqUserMap = JSONObject.parseObject(user);

			errorCode = (Integer) qqUserMap.get("ret");
			errorMsg = (String) qqUserMap.get("msg");
			if (errorCode != null && errorCode != 0) {
				throw new Exception(errorMsg);
			}

			// 请求参数
			Map<String, Object> userMap = new HashMap<>();
			userMap.put("PHOTO", qqUserMap.get("figureurl_1"));
			userMap.put("USERNAME", qqUserMap.get("nickname"));
			userMap.put("LOGINID", openid);
			userMap.put("USERTYPE", "3");
            
            // 5、登录成功在本地用户表中保存用户信息,并将用户信息放在session中
			HttpSession session = request.getSession();
			session.setAttribute("user", login(userMap));

			rtnMap.put("code", Constants.AJAX_FHZ_CG);
			rtnMap.put("message", "登录成功");
		} catch (Exception e) {
			logger.info("【ThirdPartyLoginController.qqLoginCallBack】QQ登录回调失败");
			rtnMap.put("code", Constants.AJAX_FHZ_SB);
			rtnMap.put("message", "登录失败:" + e.getMessage());
		}
		String html = "<script language='javaScript' type='text/javaScript'>window.opener.oRegisterBtn.loginCallBack("
				+ JSONObject.toJSONString(rtnMap) + ");window.close();</script>";
		return html;
	}

	/**
	 * @Title:webLoginCallBack @Description:TODO @param : @return :void @throws
	 */
	@RequestMapping("/weiboLogin")
	@ResponseBody
	public String weiboLoginCallBack(HttpServletRequest request) {
		logger.info("【ThirdPartyLoginController.webLoginCallBack】微博登录成功回调函数");
		// 返回参数
		Map<String, Object> rtnMap = new HashMap<>();
		// 1、用户登录成功后跳转到回调地址带的参数code
		String code = request.getParameter("code");

		try {
			// get auth_token
			Map<String, Object> params = new HashMap<>();
			params.put("client_id", APP_KEY_WEIBO);
			params.put("client_secret", APP_SECRECT_WEIBO);
			params.put("grant_type", "authorization_code");
			params.put("redirect_uri", REDIRECT_URI_WEIBO);
			params.put("code", code);
      
            // 2、根据code获取access token和uid
			String auth_token = HttpRequestUtil.doPost("https://api.weibo.com/oauth2/access_token", params);
			Map<String, Object> resp = JSONObject.parseObject(auth_token);

			Integer errorCode = (Integer) resp.get("error_code");
			String errorMsg = (String) resp.get("error_description");
			if (errorCode != null && errorCode != 0) {
				throw new Exception(errorMsg);
			}

			String accessToken = (String) resp.get("access_token");
			String uid = (String) resp.get("uid");

			// 3、根据accessToken和uid换取用户信息
			String userStr = HttpRequestUtil
					.doGet("https://api.weibo.com/2/users/show.json?access_token=" + accessToken + "&uid=" + uid);
			Map<String, Object> resp2 = JSONObject.parseObject(userStr);

			errorCode = (Integer) resp2.get("error_code");
			errorMsg = (String) resp2.get("error_description");
			if (errorCode != null && errorCode != 0) {
				throw new Exception(errorMsg);
			}

			String nickname = (String) resp2.get("screen_name");
			String encode = Util.getEncoding(nickname);
			// 如果字符串编码是 ISO-8859-1则转换
			if ("ISO-8859-1".equals(encode)) {
				nickname = new String(nickname.getBytes(encode), "utf-8");
			}
			// 微博180*180高清头像
			String avatar = (String) resp2.get("avatar_large");
			// 请求参数
			Map<String, Object> userMap = new HashMap<>();
			userMap.put("PHOTO", avatar);
			userMap.put("USERNAME", nickname);
			userMap.put("LOGINID", uid);
			userMap.put("USERTYPE", "5");
 
            // 4、登录成功在本地用户表中保存用户信息,并将用户信息放在session中
			HttpSession session = request.getSession();
			session.setAttribute("user", login(userMap));

			rtnMap.put("code", Constants.AJAX_FHZ_CG);
			rtnMap.put("message", "登录成功");
		} catch (Exception e) {
			logger.info("【ThirdPartyLoginController.webLoginCallBack】微博登录回调失败");
			rtnMap.put("code", Constants.AJAX_FHZ_SB);
			rtnMap.put("message", "登录失败:" + e.getMessage());
		}
		String html = "<script language='javaScript' type='text/javaScript'>window.opener.oRegisterBtn.loginCallBack("
				+ JSONObject.toJSONString(rtnMap) + ");window.close();</script>";
		return html;
	}

	/**
	 * @Title:login @Description:第三方登录 @param :@param params @param :@return @return
	 * :Map<String,Object> @throws
	 */
	private Map<String, Object> login(Map<String, Object> params) {
		logger.info("【ThirdPartyLoginController.login】登录:" + params);

		// 判断用户是否存在
		Map<String, Object> user = userServiceImpl.findUserByLoginid((String) params.get("LOGINID"));
		if (Util.isEmpty(user)) {
			// 用户不存在,则新增
			params.put("PASSWORD", ""); // 密码为空
			params.put("EMAIL", "");
			params.put("TELEPHONE", "");
			params.put("STATE", "1");
			params.put("MEMO", "");
			params.put("OPERATORID", "0");
			userServiceImpl.saveUser(params);

			user = userServiceImpl.findUserByLoginid((String) params.get("LOGINID"));
		} else {
			// 用户不存在,则新增
			user.put("USERNAME", params.get("USERNAME")); // 密码为空
			user.put("PHOTO", params.get("PHOTO"));
			userServiceImpl.saveUser(user);
		}
		return user;
	}
}

完整代码:https://github.com/kemuchen/myblog

猜你喜欢

转载自blog.csdn.net/kelei2015/article/details/84964889