精华内容
下载资源
问答
  • OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、应用上存储的私密的资源(如用户个人信息、照片、视频、联系列表),而无需将用户名和密码提供给第三方应用。(一般是对接比较...

    1.什么是OAuth2.0:

    OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。(一般是对接比较大的公司)
    OAuth允许用户提供一个令牌,openId 而不是用户名和密码来访问他们存放在特定服务提供者的数据

    2.微信公众平台OAuth2.0授权详细步骤:

    1.用户点击授权页面,向服务器发出请求
    2.第三方服务器询问用户是否同意授权给微信公众号
    3.用户同意
    4.微信服务器重定向至第三方,返回code,第三方服务器通过code获取accessTokenUrl链接
    5.第三方服务器请求accessTokenUrl链接,获取到accessToken
    6.根据accessToken,openId获取userInfoUrl
    7.第三方服务器请求userInfoUrl链接,获取用户信息
    在这里插入图片描述
    请求:127.0.0.1:8080/authorizedUrl
    用户同意:
    在这里插入图片描述
    登录成功获取到用户信息
    在这里插入图片描述

    3.修改微信公众平台配置流程:

    1.微信公众平台接口测试帐号申请链接
    https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

    2.将appID,appsecret写到配置文件中
    在这里插入图片描述
    3.关注测试公众号
    在这里插入图片描述
    4.修改回调地址 不能带有http:// 还有/ 等
    在这里插入图片描述
    在这里插入图片描述

    4.代码部分:

    构造页面授权链接
    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

    application.yml

    appid: 此处为以上页面的appID
    secret: 此处为以上页面的appsecret
    redirectUri: http://127.0.0.1:8080/callback
    
    ### 生成微信授权
    authorizedUrl: https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
    
    ###获取code后,请求以下链接获取access_token
    access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    
    ###拉取用户信息(需scope为 snsapi_userinfo)
    userinfo: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
    

    BaseApiService

    @Component
    public class BaseApiService {
    
    	public ResponseBase setResultError(Integer code, String msg) {
    		return setResult(code, msg, null);
    	}
    
    	// 返回错误,可以传msg
    	public ResponseBase setResultError(String msg) {
    		return setResult(Constants.HTTP_RES_CODE_500, msg, null);
    	}
    
    	// 返回成功,可以传data值
    	public ResponseBase setResultSuccessData(Object data) {
    		return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);
    	}
    
    	public ResponseBase setResultSuccessData(Integer code, Object data) {
    		return setResult(code, Constants.HTTP_RES_CODE_200_VALUE, data);
    	}
    
    	// 返回成功,沒有data值
    	public ResponseBase setResultSuccess() {
    		return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);
    	}
    
    	// 返回成功,沒有data值
    	public ResponseBase setResultSuccess(String msg) {
    		return setResult(Constants.HTTP_RES_CODE_200, msg, null);
    	}
    
    	// 通用封装
    	public ResponseBase setResult(Integer code, String msg, Object data) {
    		return new ResponseBase(code, msg, data);
    	}
    
    }
    

    ResponseBase

    @Getter
    @Setter
    @Slf4j
    public class ResponseBase {
    
    	private Integer rtnCode;
    	private String msg;
    	private Object data;
    
    	public ResponseBase() {
    
    	}
    
    	public ResponseBase(Integer rtnCode, String msg, Object data) {
    		super();
    		this.rtnCode = rtnCode;
    		this.msg = msg;
    		this.data = data;
    	}
    
    	public static void main(String[] args) {
    		ResponseBase responseBase = new ResponseBase();
    		responseBase.setData("123456");
    		responseBase.setMsg("success");
    		responseBase.setRtnCode(200);
    		System.out.println(responseBase.toString());
    		log.info("itmayiedu...");
    	}
    
    	@Override
    	public String toString() {
    		return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]";
    	}
    }
    

    WeiXinUtils

    @Component
    public class WeiXinUtils {
    	@Value("${appid}")
    	private String appId;
    	@Value("${secret}")
    	private String secret;
    	@Value("${redirecturi}")
    	private String redirectUri;
    	@Value("${authorizedUrl}")
    	private String authorizedUrl;
    	@Value("${access_token}")
    	private String accessToken;
    	@Value("${userinfo}")
    	private String userinfo;
    
    	public String getAuthorizedUrl() {
    		return authorizedUrl.replace("APPID", appId).replace("REDIRECT_URI", URLEncoder.encode(redirectUri));
    	}
    
    	public String getAccessTokenUrl(String code) {
    		return accessToken.replace("APPID", appId).replace("SECRET", secret).replace("CODE", code);
    	}
    
    	public String getUserInfo(String accessToken, String openId) {
    		return userinfo.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
    	}
    }
    

    HttpClientUtils

    public class HttpClientUtils {
    	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录
    
    	private static RequestConfig requestConfig = null;
    
    	static {
    		// 设置请求和传输超时时间
    		requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
    	}
    
    	/**
    	 * post请求传输json参数
    	 * 
    	 * @param url
    	 *            url地址
    	 * @param json
    	 *            参数
    	 * @return
    	 */
    	public static JSONObject httpPost(String url, JSONObject jsonParam) {
    		// post请求返回结果
    		CloseableHttpClient httpClient = HttpClients.createDefault();
    		JSONObject jsonResult = null;
    		HttpPost httpPost = new HttpPost(url);
    		// 设置请求和传输超时时间
    		httpPost.setConfig(requestConfig);
    		try {
    			if (null != jsonParam) {
    				// 解决中文乱码问题
    				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
    				entity.setContentEncoding("UTF-8");
    				entity.setContentType("application/json");
    				httpPost.setEntity(entity);
    			}
    			CloseableHttpResponse result = httpClient.execute(httpPost);
    			// 请求发送成功,并得到响应
    			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
    				String str = "";
    				try {
    					// 读取服务器返回过来的json字符串数据
    					str = EntityUtils.toString(result.getEntity(), "utf-8");
    					// 把json字符串转换成json对象
    					jsonResult = JSONObject.parseObject(str);
    				} catch (Exception e) {
    					logger.error("post请求提交失败:" + url, e);
    				}
    			}
    		} catch (IOException e) {
    			logger.error("post请求提交失败:" + url, e);
    		} finally {
    			httpPost.releaseConnection();
    		}
    		return jsonResult;
    	}
    
    	/**
    	 * post请求传输String参数 例如:name=Jack&sex=1&type=2
    	 * Content-type:application/x-www-form-urlencoded
    	 * 
    	 * @param url
    	 *            url地址
    	 * @param strParam
    	 *            参数
    	 * @return
    	 */
    	public static JSONObject httpPost(String url, String strParam) {
    		// post请求返回结果
    		CloseableHttpClient httpClient = HttpClients.createDefault();
    		JSONObject jsonResult = null;
    		HttpPost httpPost = new HttpPost(url);
    		httpPost.setConfig(requestConfig);
    		try {
    			if (null != strParam) {
    				// 解决中文乱码问题
    				StringEntity entity = new StringEntity(strParam, "utf-8");
    				entity.setContentEncoding("UTF-8");
    				entity.setContentType("application/x-www-form-urlencoded");
    				httpPost.setEntity(entity);
    			}
    			CloseableHttpResponse result = httpClient.execute(httpPost);
    			// 请求发送成功,并得到响应
    			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
    				String str = "";
    				try {
    					// 读取服务器返回过来的json字符串数据
    					str = EntityUtils.toString(result.getEntity(), "utf-8");
    					// 把json字符串转换成json对象
    					jsonResult = JSONObject.parseObject(str);
    				} catch (Exception e) {
    					logger.error("post请求提交失败:" + url, e);
    				}
    			}
    		} catch (IOException e) {
    			logger.error("post请求提交失败:" + url, e);
    		} finally {
    			httpPost.releaseConnection();
    		}
    		return jsonResult;
    	}
    
    	/**
    	 * 发送get请求
    	 * 
    	 * @param url
    	 *            路径
    	 * @return
    	 */
    	public static JSONObject httpGet(String url) {
    		// get请求返回结果
    		JSONObject jsonResult = null;
    		CloseableHttpClient client = HttpClients.createDefault();
    		// 发送get请求
    		HttpGet request = new HttpGet(url);
    		request.setConfig(requestConfig);
    		try {
    			CloseableHttpResponse response = client.execute(request);
    
    			// 请求发送成功,并得到响应
    			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
    				// 读取服务器返回过来的json字符串数据
    				HttpEntity entity = response.getEntity();
    				String strResult = EntityUtils.toString(entity, "utf-8");
    				// 把json字符串转换成json对象
    				jsonResult = JSONObject.parseObject(strResult);
    			} else {
    				logger.error("get请求提交失败:" + url);
    			}
    		} catch (IOException e) {
    			logger.error("get请求提交失败:" + url, e);
    		} finally {
    			request.releaseConnection();
    		}
    		return jsonResult;
    	}
    
    }
    

    OauthController

    @Controller
    public class OauthController extends BaseApiService {
    
    	@Autowired
    	private WeiXinUtils weiXinUtils;
    	private String errorPage = "errorPage";
    
    	// 生成授权链接
    	@RequestMapping("/authorizedUrl")
    	public String authorizedUrl() {
    		return "redirect:" + weiXinUtils.getAuthorizedUrl();
    	}
    
    	// 微信授权回调地址
    	@RequestMapping("/callback")
    	public String callback(String code, HttpServletRequest request) {
    		// 1.使用Code 获取 access_token
    		String accessTokenUrl = weiXinUtils.getAccessTokenUrl(code);
    		//通过请求获取的accessTokenUrl链接 获取到accessToken
    		JSONObject resultAccessToken = HttpClientUtils.httpGet(accessTokenUrl);
    		boolean containsKey = resultAccessToken.containsKey("errcode");
    
    		if (containsKey) {
    			request.setAttribute("errorMsg", "系统错误!");
    			return errorPage;
    		}
    		// 2.使用access_token获取用户信息
    		String accessToken = resultAccessToken.getString("access_token");
    		String openid = resultAccessToken.getString("openid");
    		// 3.拉取用户信息(需scope为 snsapi_userinfo)
    		String userInfoUrl = weiXinUtils.getUserInfo(accessToken, openid);
    		JSONObject userInfoResult = HttpClientUtils.httpGet(userInfoUrl);
    		System.out.println("userInfoResult:" + userInfoResult);
    		request.setAttribute("nickname", userInfoResult.getString("nickname"));
    		request.setAttribute("city", userInfoResult.getString("city"));
    		request.setAttribute("headimgurl", userInfoResult.getString("headimgurl"));
    		return "info";
    	}
    
    }
    
    
    展开全文
  • 社交网络
  • 最近公司要求实现一个绑定新浪微博 实现同步微博登录效果。 花了我一段时间 最算实现了效果。下面我讲讲我的实现过程,希望给予想做这方面开发的一点帮助! 首先,我们要进去新浪微博开放平台...
    最近公司要求实现一个绑定新浪微博  实现同步微博登录效果。
    

    花了我一段时间 最算实现了效果。下面我讲讲我的实现过程,希望给予想做这方面开发的人一点帮助!

    首先,我们要进去新浪微博开放平台http://open.weibo.com/创建一个我们的网站

    在创建网站之前,如果你没身份验证,首先是要身份验证的(大概几个小时内可以审批下来)

    根据条件创建网站,中间注意要你复制一段代码到发布的项目中去,然后等待审批(估计要点时间)

    中间会返回一个AppKey以及一个AppSecret ;

    审批通过之后  才正式进行我们开发过程  

    我们先看看整个流程http://www.cnblogs.com/highend/archive/2012/07/06/oautn2_authorization_code.html

    管理中心>接口管理 里面有授权后的所有接口可以调用

    授权机制里面。注意填写它的回调地址 如果测试用户可以填写http://127.0.0.1/Weibo.aspx(Weibo.aspx 为我们回调的页面)

    public partial class wbAPI : System.Web.UI.Page
        {
            public const string AppKey = "207788581"; //请自行设置AppKey
            public const string AppSecret = "cba11dad8522a7b1f32aefde396be"; //请自行设置AppSecret
            public const string CallbackUrl = "http://www.miutrip.com/Weibo.aspx"; //请自行设置回调地址,一般这里不用填应用实际地址,填站内应用地址也是可以的
    
    
            protected void Page_Load(object sender, EventArgs e)
            {
    
                #region  注意事项(绑定新浪微博)
                /**
              *这段代码放入你的触发时间处。绑定按钮,一般是在别的页面跳过
              * 127.0.0.1本机IP  一般用于测试
              * 8080 本机端口号
              * Weibo.aspx为当前你的页面 
              * 授权申请成功之后,配置的返回路径应该为 http://www.miutrip.com/Weibo.aspx
              * 调用微博信息 要添加NetDimension.Weibo.DLL文件
              */
    
                // href="https://api.weibo.com/oauth2/authorize?client_id=207778561&response_type=code&redirect_uri=http://127.0.0.1:8080/Weibo.aspx"
               
                #endregion 
    
                if (!IsPostBack)
                {
                    var sign = Request["code"];
                    //var sign = "b3eb3bccbf4cd9399236a02a81cde4bf";
    
                    var oauth = new NetDimension.Weibo.OAuth(AppKey, AppSecret, CallbackUrl);
                    /*
                     * 正常的流程或Web流程:
                     * 1. 获取授权地址
                     * 2. 访问授权地址
                     * 3. 授权成功后自动跳转至callback指定的网站,并获得code
                     * 4. 通过code换取access token
                     */
                    if (!string.IsNullOrEmpty(sign))
                    {
                        var accessToken = oauth.GetAccessTokenByAuthorizationCode(sign).Token;//注意:callback指定的url必须一致
    
                        oauth = new OAuth(AppKey, AppSecret, accessToken, "");
                        var sina = new Client(oauth);
                        var userInfo = sina.API.Dynamic.Users.Show(uid: sina.API.Entity.Account.GetUID());
                       //userInfo就为我们得到的用户信息
                        Response.Write(userInfo);
                        //Server.Transfer("CorpActivate.aspx", true);
                    }
                }
    
            }
    


     这个页面实现,我们还要添加DLL:NetDimension.Weibo.dll 可以网上下载


    微博入口:

    <a href="#" οnclick="openwin()" class="wb_xl">新浪微博登陆</a>
    
    
     function openwin() {
                window.open("https://api.weibo.com/oauth2/authorize?client_id=144119704&response_type=code&redirect_uri=http://www.miutrip.com/Weibo.aspx", "newwindow", "height=100, width=400, toolbar =no, menubar=no, scrollbars=no, resizable=no, location=no, status=no") //写成一行
            }

    client_id就为appkey  如果微博入口有多个,处理出来不太方便

    可以在回调地址,也就是redirect_uri=

    http://www.miutrip.com/Weibo.aspx?sinatype=Login
    后面带一个参数   来区分那个入口传过来的值。

    在weibo.aspx 获取就可以 

    string sinatype = Request.QueryString["Login"];


    如果还有什么不了解,可以加我QQ315676647@qq.com   写上你的情况



    展开全文
  • 探针访客的QQ信息功能 1、可探针到访客的QQ号码 ...老板在外面也可以用手机登录小Q来查询访问您网站的用户QQ号码哦,关键字来路也可以查询的到哦。小Q目前是国内同行业独家具有客户端 网页“双模查询”功能哦。
  • 前言个人网站最近增加了评论功能,为了方便用户不用注册就可以评论,对接了 QQ 和微博这 2 大常用软件的一键登录,总的来说其实都挺简单的,可能会有一点小坑,但不算多,完整记录下来方便后来快速对接。...

    如果你对我的文章感兴趣,关注公众号和加QQ群继续讨论,一起进步,下面是正文开始

    bfb4f81be009825b3f56998c95545166.png

    1ff426e7ec855ca8c012c4e23a7da54d.png

    1. 前言

    个人网站最近增加了评论功能,为了方便用户不用注册就可以评论,对接了 QQ 和微博这 2 大常用软件的一键登录,总的来说其实都挺简单的,可能会有一点小坑,但不算多,完整记录下来方便后来人快速对接。

    2. 后台设计在真正开始对接之前,我们先来聊一聊后台的方案设计。既然是对接第三方登录,那就免不了如何将用户信息保存。首先需要明确一点的是,用户在第三方登录成功之后,我们能拿到的仅仅是一个代表用户唯一身份的ID(微博是真实uid,QQ是加密的openId)以及用来识别身份的accessToken,当然还有昵称、头像、性别等有限资料,对接第三方登录的关键就是如何确定用户是合法登录,如果确定这次登录的和上次登录的是同一个人并且不是假冒的。其实这个并不用我们特别操心,就以微博登录为例,用户登录成功之后会回调一个code 给我们,然后我们再拿code去微博那换取accessToken,如果这个code是用户乱填的,那这一关肯定过不了,所以,前面的担心有点多余。另外一个问题就是如何和现有用户系统打通,有的网站在用户已经登录成功之后还要用户输入手机号和验证码,或者要用户重新注册账号和密码来绑定第三方账户,感觉这种实现用户体验非常差,碰到这种网站我一般都是直接关掉,都已经登录了还让用户注册,什么鬼!由于我做的是评论功能,我并不希望评论用户和现有用户表打通,所以就不存在这件事了,如果想打通的话,我觉得无非就是登录成功之后默认往老用户表插入一条数据,然后和OpenUser表关联起来,判断用户是否登录时把OpenUser的鉴权也加进去就OK了。本文的后台以Java为例。

    2.1. 数据库设计

    再来说说数据库设计,为了系统的扩展性,我有一个专门的OpenUser表用来存放第三方登录用户,主要字段如下:

    176537fc63f4bbf7f885f62e18c8d961.png

    这样设计理论上就可以无限扩展了。

    2.2. 鉴权流程

    这里我只是说说我的方案,把accessToken写入cookie肯定是不安全的,因为accessToken相当于是第三方网站的临时密码,被别人窃取了就可以随意拿来干坏事了。可以在用户登录成功之后我们自己生成一个token,这样的token即使泄露了顶多就是被人拿来随意评论,损失不大,但是如果accessToken被泄露了,以微博为例,人家可以利用这个accessToken随意发微博、删微博、加关注等等,很危险。当然,如果不想token泄露的话也可以通过绑定IP等方式来限制。鉴权的话就是首先判断cookie中是否有我们自己的token,然后判断是否合法,合法再判断第三方授权是否已过期等等。

    QQ登陆

    3.1. 实名认证

    QQ登录我们对接的是QQ互联,地址:https://connect.qq.com ,首先需要注册成为开发者并实名认证,需要手持身份证照片,具体就不讲了

    3.2. 创建应用

    进入应用管理页面(https://connect.qq.com/manage.html#/)创建应用,根据实际需要是创建网站应用还是移动应用,我这里是网站应用:

    a87588262053eeb4c2e9e6a47b1acfe8.png

    第一步:

    a1039b784ad71688d5cd98abfbb4e46e.png

    第二步:

    a096d0a08b262226c626b674f6958bda.png

    提交完之后会自动提交审核,基本上就是审核你的资料和备案的资料是否一致,所有资料必须和备案资料一模一样,否则审核不会通过:

    197c5110776b3ea0d20f24c763b2cab7.png

    当然,这些资料后面还是可以修改的。申请成功之后你会得到appIdappKey

    3.3. 引导用户登录

    这里可以下载一些视觉素材,在页面合适位置放一个QQ登录按钮,点击时引导用户进入授权页面:

    b2ed2a6b4e5021b0395d48096a2887bc.png

    代码:

    function openWindow(url, width, height)
    {
        width = width || 600;
        height = height || 400;
        var left = (window.screen.width - width) / 2;
        var top = (window.screen.height - height) / 2;
        window.open(url, "_blank", "toolbar=yes, location=yes, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=no, copyhistory=yes, left="+left+", top="+top+", width="+width+", height="+height);
    }
    
    function qqLogin()
    {
        var qqAppId = '424323422'; // 上面申请得到的appid
        var qqAuthPath = 'http://www.test.com/auth'; // 前面设置的回调地址
        var state = 'fjdslfjsdlkfd'; // 防止CSRF攻击的随机参数,必传,登录成功之后会回传,最好后台自己生成然后校验合法性
        openWindow(`https://graph.qq.com/oauth2.0/authorize?response_type=token&client_id=${qqAppId}&redirect_uri=${encodeURIComponent(qqAuthPath)}&state=${state}`);
    }

    然后会打开一个授权页面,这个页面大家应该都熟悉:

    47acf934f276d26a30a206c79eb76b5d.png

    然后到了这里我就碰到一个问题了,官方文档(https://wiki.connect.qq.com)写的是登录成功之后首先会回传一个code,然后再拿code调接口换取accessToken,然后我试了很多次也换过2个账号发现每次都是直接返回了accessToken,帮我省了一步了,不知道是什么情况,郁闷。微信搜索 Web项目聚集地 获取更多实战教程。

    3.4. 拿到accessToken

    现在假设我们都是直接拿到accessToken(因为我暂时还没搞明白QQ为啥会直接返回,跟文档说的不一样),但是授权回调时accessToken会被放在 # 后面,URL地址中的hash值好像不会被传到后台(貌似是这样,如有不正确欢迎评论指正),所以只能写一个下面这样的临时页面:

    @RequestMapping("/authqq")
    public void authQQ(HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        // QQ登录有点特殊,参数放在#后面,后台无法获取#后面的参数,只能用JS做中间转换
        String html =   "<!DOCTYPE html>" +
                        "<html lang="zh-cn">" +
                        "<head>" +
                        "   <title>QQ登录重定向页</title>" +
                        "   <meta charset="utf-8"/>" +
                        "</head>" +
                        "<body>" +
                        "   <script type="text/javascript">" +
                        "   location.href = location.href.replace('#', '&').replace('auth_qq', 'auth_qq_redirect');" +
                        "   
    </script>
    " +
                        "</body>" +
                        "</html>";
        response.getWriter().print(html);
    }

    3.5. 获取openId

    根据accessToken调接口获取用户的openId,特别注意这个openId是相对于QQ号+appId唯一的,换句话说同一个QQ号登录2个不同appId时获取到的openId是不同的。顺便说一句,QQ登录的相关接口做的还真够“随便”的,全部都是最简单的get请求,所以对接起来非常顺利。 微信搜索 Web项目聚集地 获取更多实战教程。

    直接看代码:

    // 根据accessToken换取openId
    // 错误示例:callback( {"error":100016,"error_description":"access token check failed"} );
    // 正确示例:callback( {"client_id":"10XXXXX49","openid":"CF2XXXXXXXX9F4C"} );
    String result = HttpsUtil.get("https://graph.qq.com/oauth2.0/me?access_token=" + accessToken);
    Map<String, Object> resp = parseQQAuthResponse(result); // 这个方法就是把结果转Map
    // 欢迎关注 Web项目聚集地 获取更多实战教程
    Integer errorCode = (Integer)resp.get("error");
    String errorMsg = (String)resp.get("error_description");
    String openId = (String)resp.get("openid");
    if(errorCode != null) return new ErrorResult(errorCode, "获取QQ用户openId失败:"+errorMsg);

    3.6. 获取用户头像昵称等信息

    // 获取用户昵称、头像等信息,{ret: 0, msg: '', nickname: '', ...} ret不为0表示失败
    result = HttpsUtil.get("https://graph.qq.com/user/get_user_info?access_token="+accessToken+"&oauth_consumer_key="+appId+"&openid="+openId);
    resp = JsonUtil.parseJsonToMap(result);
    // 欢迎关注 Web项目聚集地 获取更多实战教程
    Integer ret = (Integer)resp.get("ret");
    String msg = (String)resp.get("msg");
    if(ret != 0) return new ErrorResult("获取用户QQ信息失败:"+msg);
    
    // 用户昵称可能存在4个字节的utf-8字符,MySQL默认不支持,直接插入会报错,所以过滤掉
    String nickname = StringUtil.filterUtf8Mb4((String)resp.get("nickname")).trim(); // 这个方法可以自行百度
    // figureurl_qq_2=QQ的100*100头像,figureurl_2=QQ 100&100空间头像,QQ头像不一定有,空间头像一定有
    String avatar = (String)resp.get("figureurl_qq_2");
    if(StringUtil.isBlank(avatar)) avatar = (String)resp.get("figureurl_2");
    String gender = (String)resp.get("gender");

    3.7. 注意事项到了这一步基本上涉及第三方的就结束了,是不是很简单?后面无非就是如何插入数据库、如何保存token、写入session等。有几点注意事项:

    • 需要注意数据库中是否已经有改用户,没有的添加,有的修改,不要重复添加了;
    • QQ昵称昵称有各种奇奇怪怪的字符,包括emoji,MySQL默认没有开启utf8mb4,直接插入会报错,所以需要过滤掉;
    • 需要做好对各种错误的兼容;
    • 接口会同时返回QQ头像和空间头像,QQ头像不一定有,空间头像一定有;
    • 回调地址必须和申请的域名一致,否则会报错。
    • QQ互联有个特大的bug,有时候显示已登录但是点击授权管理一直报错,此时只需要退出重新登录即可;
    • 授权之后用户可能会在过期之前提前取消授权;
    • 微信搜索 Web项目聚集地 获取更多实战教程。

    相关文档官网已经写得比较细了,但是比较乱:http://wiki.connect.qq.com/

    对接微博登陆

    4.1. 实名认证

    这个我就不具体讲了,登录 http://open.weibo.com/ 很容易找到相关入口,注册成为开发者,实名认证,一模一样的。

    4.2. 创建应用

    点击链接 http://open.weibo.com/apps/new?sort=web 创建web应用:

    6b442f97fd5c92769b3967de02993ad0.png

    创建成果后完善相关信息,主要是下面这些:

    01e6f3268a94f0f4a7cdc06872a0f1ae.png

    我就不一一介绍了,都看得懂。微博登录不需要网站一定要备案,但对网站本身有一定要求,不能弄一个空壳网站让人家去审核,肯定审核不通过的。

    有关微博的对接可以参考我好几年前写的一篇文章:

    http://www.cnblogs.com/liuxianan/archive/2012/11/11/2765123.html

    4.3. 引导用户登录

    微博视觉素材(https://open.weibo.com/wiki/微博标识下载)下载在这里,页面合适位置放一个登录按钮:

    functionweiboLogin(){
    let weiboAppId = '432432';
    let weiboAuthPath = 'http://www.test.com/authweibo';    
    openWindow(`https://api.weibo.com/oauth2/authorize?client_id=${weiboAppId}&response_type=code&redirect_uri=${encodeURIComponent(weiboAuthPath)}`);
    } 
    

    微博登录有一个好处,第一次登录需要授权,后面第二次登录时只会一闪而过自动就登录成功了,都不需要点一下,用户体验非常好,看下图:

    32cc58c5478e11556f5410433a3c5dd8.gif

    4.4. 获取accessToken

    登录成功会返回一个code,根据code换取accessToken:

    String params = "client_id=" + appId
            + "&client_secret=" + appSecret
            + "&grant_type=authorization_code"
            + "&redirect_uri=" + URLUtil.encode(authPath)
            + "&code=" + code;
    // 用code换取accessToken
    String result = HttpsUtil.post("https://api.weibo.com/oauth2/access_token", params);
    Map<String, Object> resp = JsonUtil.toObject(result, new TypeReference<Map<String, Object>>(){});
    
    Integer errorCode = (Integer)resp.get("error_code");
    String error = (String)resp.get("error");
    String errorMsg = (String)resp.get("error_description");
    if(errorCode != null && errorCode != 0) return new ErrorResult(errorCode, error + (errorMsg==null?"":errorMsg));
    String accessToken = (String)resp.get("access_token");
    String uid = (String)resp.get("uid"); // 这个uid就是微博用户的唯一用户ID,可以通过这个id直接访问到用户微博主页
    int expires = (Integer)resp.get("expires_in"); // 有效期单位秒

    4.5. 获取用户头像等信息

    // 用uid和accessToken换取用户信息
    String result = HttpsUtil.get("https://api.weibo.com/2/users/show.json?access_token="+accessToken+"&uid="+uid);
    Map<String, Object> resp = JsonUtil.toObject(result, new TypeReference<Map<String, Object>>(){});
    
    errorCode = (Integer)resp.get("error_code");
    error = (String)resp.get("error");
    errorMsg = (String)resp.get("error_description");
    if(errorCode != null && errorCode != 0) return new ErrorResult(errorCode, error + (errorMsg==null?"":errorMsg));
    
    String nickname = (String)resp.get("screen_name");
    // 微博180*180高清头像
    String avatar = (String)resp.get("avatar_large");
    String gender = (String)resp.get("gender");
    gender = "m".equals(gender) ? "男" : ("f".equals(gender) ? "女" : "");

    此涉及第三方的东西都完了,剩下的就是用户自己保存到数据库、写入token保存 session 以及鉴权接口开发了。

    4.6. 注意事项
    
    • 微博接口都有频率限制,不过一般不会超过;
    • 需做好错误兼容;
    • 微博直接返回的uid,可以根据这个uid直达用户微博主页 https://weibo.com/u/xxxxx ,所以可以把用户头像链接到这里;
    • 其实也有现成的js-sdk,可以根据自己实际需要选择是否使用;
    • 微博的接口是https,并且是post,需要注意;

    如果你对我的文章感兴趣,关注公众号和加QQ群继续讨论,一起进步

    bfb4f81be009825b3f56998c95545166.png

    1ff426e7ec855ca8c012c4e23a7da54d.png
    展开全文
  • 以前也做过类似于新闻小偷之类的东西,就是利用WebRequest从请求的URL获取信息后进行分析,然后显示。记得当时老板让做一个搜索时抓取程序,想把这边几个BBS的信息都能纳入搜索范围。因为有些BBS的搜索功能必须登录...
    以前也做过类似于新闻小偷之类的东西,就是利用WebRequest从请求的URL获取信息后进行分析,然后显示。记得当时老板让做一个搜索时抓取程序,想把这边几个BBS的信息都能纳入搜索范围。因为有些BBS的搜索功能必须登录后才能使用,所以当时我想破了脑子也没办法,最后认为这个任务根本没法做,就没往下思考。今天在CSDN上看到一个帖子,才知道原来这并非不可实现的,其实早己有人这样做过。要做到这些,其要点有两个:  

    1、通过附加一个cookiecontainer到httprequest对象中,可以得到登录后返回的代表SESSION ID的COOKIE。  

    2 、将此COOKIE包含在一个cookiecontainer中并附加到另一个HTTPREQUEST请求中,则可以实现SESSION的还原。

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    //using System.Data.OleDb;
    
    using System.Drawing;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    using System.Net;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;
    using Microsoft.Data.Odbc;
    namespace PdfTest
    {
    /// <summary>
    
    /// Summary description for WebForm1.
    
    /// </summary>
    
    public class getHttpInfo : System.Web.UI.Page
    {
    protected static string cookieheader;
    private void Page_Load(object sender, System.EventArgs e)
    {
    // Put user code to initialize the page here
    
    string strResult;
    if (HttpContext.Current.Application["cookieheader"] != null)
    {
    cookieheader = (string) HttpContext.Current.Application["cookieheader"];
    }
    else
    {
    //Login into the website and keep the cookie for the session in the application variable
    
    string strLogin = Login("http://www.thesiteyouwanttovisit/theloginpage.asp", "Action=&USERID=&Password=");
    
    }
    strResult = getPage("http://www.thesiteyouwanttovisit/theloginpage.asp", "Action=&data=");
    
    //Write the result to htm file
    
    FileStream htmFile = new FileStream(@"c:\save.htm", FileMode.OpenOrCreate);
    StreamWriter sw = new StreamWriter(htmFile);
    sw.Write(strResult);
    sw.Close();
    htmFile.Close();
    // output the result
    
    Response.Write(strResult);
    }
    public static string Login(String url, String paramList)
    {
    HttpWebResponse res = null;
    string strResult = "";
    try
    {
    HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    req.AllowAutoRedirect = false;
    CookieContainer cookieCon = new CookieContainer();
    req.CookieContainer = cookieCon;
    StringBuilder UrlEncoded = new StringBuilder();
    Char[] reserved = { '?', '=', '&' };
    byte[] SomeBytes = null;
    if (paramList != null)
    {
    int i = 0, j;
    while (i < paramList.Length)
    {
    j = paramList.IndexOfAny(reserved, i);
    if (j == -1)
    {
    UrlEncoded.Append(HttpUtility.UrlEncode(paramList.Substring(i, paramList.Length - i)));
    break;
    }
    UrlEncoded.Append(HttpUtility.UrlEncode(paramList.Substring(i, j - i)));
    UrlEncoded.Append(paramList.Substring(j, 1));
    i = j + 1;
    }
    SomeBytes = Encoding.UTF8.GetBytes(UrlEncoded.ToString());
    req.ContentLength = SomeBytes.Length;
    Stream newStream = req.GetRequestStream();
    newStream.Write(SomeBytes, 0, SomeBytes.Length);
    newStream.Close();
    }
    else
    {
    req.ContentLength = 0;
    }
    res = (HttpWebResponse) req.GetResponse();
    cookieheader = req.CookieContainer.GetCookieHeader(new Uri(url));
    HttpContext.Current.Application.Lock();
    HttpContext.Current.Application["cookieheader"] = cookieheader;
    HttpContext.Current.Application.UnLock();
    Stream ReceiveStream = res.GetResponseStream();
    Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
    StreamReader sr = new StreamReader(ReceiveStream, encode);
    Char[] read = new Char[256];
    int count = sr.Read(read, 0, 256);
    while (count > 0)
    {
    String str = new String(read, 0, count);
    strResult += str;
    count = sr.Read(read, 0, 256);
    }
    }
    catch (Exception e)
    {
    strResult = e.ToString();
    }
    finally
    {
    if (res != null)
    {
    res.Close();
    }
    }
    return strResult;
    }
    public static string getPage(String url, String paramList)
    {
    HttpWebResponse res = null;
    string strResult = "";
    try
    {
    HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
    req.Method = "POST";
    req.KeepAlive = true;
    req.ContentType = "application/x-www-form-urlencoded";
    CookieContainer cookieCon = new CookieContainer();
    req.CookieContainer = cookieCon;
    req.CookieContainer.SetCookies(new Uri(url), cookieheader);
    StringBuilder UrlEncoded = new StringBuilder();
    Char[] reserved = { '?', '=', '&' };
    byte[] SomeBytes = null;
    if (paramList != null)
    {
    int i = 0, j;
    while (i < paramList.Length)
    {
    j = paramList.IndexOfAny(reserved, i);
    if (j == -1)
    {
    UrlEncoded.Append(HttpUtility.UrlEncode(paramList.Substring(i, paramList.Length - i)));
    break;
    }
    UrlEncoded.Append(HttpUtility.UrlEncode(paramList.Substring(i, j - i)));
    UrlEncoded.Append(paramList.Substring(j, 1));
    i = j + 1;
    }
    SomeBytes = Encoding.UTF8.GetBytes(UrlEncoded.ToString());
    req.ContentLength = SomeBytes.Length;
    Stream newStream = req.GetRequestStream();
    newStream.Write(SomeBytes, 0, SomeBytes.Length);
    newStream.Close();
    }
    else
    {
    req.ContentLength = 0;
    }
    res = (HttpWebResponse) req.GetResponse();
    Stream ReceiveStream = res.GetResponseStream();
    Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
    StreamReader sr = new StreamReader(ReceiveStream, encode);
    Char[] read = new Char[256];
    int count = sr.Read(read, 0, 256);
    while (count > 0)
    {
    String str = new String(read, 0, count);
    strResult += str;
    count = sr.Read(read, 0, 256);
    }
    }
    catch (Exception e)
    {
    strResult = e.ToString();
    }
    finally
    {
    if (res != null)
    {
    res.Close();
    }
    }
    return strResult;
    }
    
    #region Web Form Designer generated code
    
    override protected void OnInit(EventArgs e)
    {
    //
    
    // CODEGEN: This call is required by the ASP.NET Web Form Designer.
    
    //
    
    InitializeComponent();
    base.OnInit(e);
    }
    /// <summary>
    
    /// Required method for Designer support - do not modify
    
    /// the contents of this method with the code editor.
    
    /// </summary>
    
    private void InitializeComponent()
    {
    this.Load += new System.EventHandler(this.Page_Load);
    }
            #endregion
    
    }
    }
    展开全文
  • 一个WinHttp.WinHttpRequest编程的例子,支持采集有验证码的会员系统,可以实时获取51.la网站统计信息。第一次访问必须输入验证码(如果有几百几千访问,只有第一个人需要输入)。稍作修改,可以偷取任何网站信息...
  • 想要从企查查爬取企业信息,如果没有登录直接检索,很多信息都被隐藏了,如图:爬虫想要登录,如果与网站上的验证码正面硬刚,可能会比较麻烦,首先要拖动滑块:然后还要输入验证码:可能有些手段能够解决,但是今天...
  • Python爬虫之模拟登录豆瓣获取最近看过的电影

    万次阅读 热门讨论 2015-08-03 11:56:31
    首先,你应该要了解网站登录的流程以及你需要post的信息,以豆瓣为例: 这就是你需要提交的信息了,包括用户名和密码,以及验证码和验证码的ID,看到这可能有会想我怎么知道验证码的ID,各位放心,在页面加载时就...
  • 最近学院要做一个投票功能的网站,考虑到很多会用手机登录,那么我们应该这么获取独一无二的用户标识呢? 目前想用ip地址来区分,但是手机上网的IP地址是动态的,这就很尴尬了。之前也考虑过用微信号区分,但是...
  • 测试目标为APP,故使用安卓模拟器,安装应用程序百度搜索app无root抓包,下载安装基本配置,安装证书,设置屏密码开启抓包登录目标app获取参数等信息一路狂奔找可控参数,后发现通过搜寻附近的人和的名称存在信息...
  • 云闪付app注册登录常见问答1、如何注册成为云闪付...2、持卡主动获取和使用银联增值服务有哪些前提条件?(1)注册成为云闪付APP用户;(2)至少添加一张银联卡。3、如何通过持卡服务网站注册成为云闪付APP用户?访...
  • 那些你认为是隐私的东西,在各类手机APP、电脑软件、网站上,凡是你用个人信息等登陆过的地方你就是个透明。基本上所有的应用都会在用户安装时索要权限,有的软件你不给权限根本就无法使用。微信、支付宝这些有名...
  • 本文介绍的这种方法对于我们有时候忘记了登陆用户名和密码很有帮助,但是也从侧面透露着我们在其它设备上登录我们自己的社交网站信息是多么的不安全,换句话说,任何都可以轻易地获取你的账户信息。 在我们登录...
  • 于是非常多的使用授权登录的方法,但其实授权登录时也是需要获取一定的个人信息的,难免暴露一些个人隐私,有时候授权了几百个应用自己都还不知道,那么如果不用了该如何取消授权呢?取消QQ授权取消QQ授权的方法...
  • 登录公司的网站,在其他的电脑上登录都正常,但是在唯独在我这朋友的机器上登录不上去,总是报无法连接的页面。网络配置同其他的配置一样,更奇怪的是机器同其他同事的机器配置都一样。自动获取IP,DNS上网。 ...
  • 通过博客园站内信,有很多私信我,是怎么获取到那么多隐私信息,让我传授给他方法,以便窥探别人的隐私。   为了不每次话很长时间都解释我运行模式,这里统一说明一下,我们的系统都是基于用户授权登录模式开发...
  • 现如今大数据时代,数据的...许多写爬虫的朋友第一个碰到的难题就是:在对某个网站进行了持续一段时间的爬取之后,网站的反爬虫机制会返回一些错误的结果给爬虫,503、407,,,,要不就是强制给你跳转到登录界面,让
  • 掌握基本的需求获取与分析方法; 掌握用例图、类图、活动图、顺序图的画法; 熟悉一种UML绘图软件的基本用法; 二、实验内容 1、按照以下关于电子商务网站的描述,绘制一个用例图;绘制一个类图;提取其中一个...
  • 偶们常说的第三方是指的微信,qq,新浪这些第三方,因为现在基本每个都有qq或者微信,那么我们就可以通过这些第三方进行登录。而这些网站比如慕课网是通过第三方获取用户的基本信息 它会有个勾选按钮,提示是否...
  • 百度上有说可以通过小程序实现,但再去申请小程序也是麻烦,既然公众号能获取到会员的很多信息,并且能实现自动登录,我何不在公众平台下功夫?弄了半个多月总是写了出来,心路历程我附在最下面,有兴趣的朋
  • OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系列表),而无需将用户名和密码提供给第三方应用。...
  • 根据9月10日公安部公布的徐玉玉案诈骗细节,嫌疑利用技术手段攻破“山东省2016高考网上报名信息系统”, 并在网站植入木马病毒,获取网站后台登录权限,盗取了包括徐玉玉在内的大量考生报名信息。 根据公开报道...
  • 1、网站首页 - 预设了会员登录、行业分类、轮播广告、最新项目推荐、品牌新闻、视频、加盟资讯、顾问咨询等板块,也可以自行增设或调整板块。 2、找项目 - 可以按分类或条件搜索查找项目,具有列表显示和橱窗显示...
  • 在进行网站开发的时候,程序员由于对用户输数据缺乏全面判断或者过滤不严导致服务器执行一些恶意信息,比如用户信息查询等。黑客可以根据恶意程序返回的结果获取相应的信息。这就是所谓的SQL注入漏洞。 sql注入...
  • 7、推广营销:支持用户前台获取推荐连接,并邀请好友购买、返现; 8、支付接口:默认集成支付宝和财付通接口;可后台设置,或添加银行转账信息等; 9、团购流程:支持生成唯一订单号(方便沟通)、可切换不同的...
  • 5、房产经济管理: 房产经济会员登录后可以发布管理房源信息,拥有独立的个人主页。 6、会员通行证: 会员统一在总网注册后,即可以在网站各频道内实现统一登录,比如会员在二手房频道注册会员后,即可在论坛、...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 232
精华内容 92
关键字:

获取网站登录人信息