• ASP.NET MVC通过OAuth调用Google API获取用户信息


    一边享受着乡村的宁静,一边写着博客,也是一种惬意。

    喜欢解决问题后写一篇博客。通过文字表达出来,会加深自己的理解,还经常会有新的收获,甚至会找到更好的解决方法。同时,还能分享给别人。一举多得,何乐而不为呢?

    这次要解决的问题是如何在用户注册时验证用户的邮箱?

    通常的解决方法是给用户的邮箱发一封激活邮件。但这个方法有以下几个问题:

    • 从发出邮件至收到邮件,可能会有延时。
    • 邮件可能会被当作垃圾邮件处理
    • 用户可能会填错了邮箱,更糟糕的情况是用户不知道自己填错了邮箱。

    这次要解决的问题的更具体的场景是如何验证用户的gmail邮箱?

    我们采用的解决方法是通过OAuth调用Google API获取用户的gmail地址

    于是,问题就变为如何在ASP.NET MVC中通过OAuth调用Google API

    必看的两个文档:

    Using OAuth 2.0 to Access Google APIs

    Using OAuth 2.0 for Web Server Applications

    我们的OAuth应用场景是Web Server Applications,对应的序列图如下:

    简单描述一下整个流程:

    1. 你在网站上提供一个Google OAuth登录的链接
    2. 用户点击这个链接进入Google登录页面进行登录
    3. 用户登录成功后,会显示授权页面。
    4. 用户授权成功后,Google会自动重定向至你的网站页面,并传递authorization code给你。
    5. 通过这个authorization code,向Google OAuth服务器请求access_token。
    6. 拿到access_token之后,调用Google API获取用户信息。

    下面是具体的实现步骤:

    1. 进入Google APIs Console,创建一个Project,并创建Client ID,如下图:

    得到这些信息 —— Client ID, Email address, Client secret, Redirect URIs

    2. 创建一个空的ASP.NET MVC项目

    3. 在web.config中添加相应的appSetting保存第1步得到的Client ID相关信息

    <appSettings>
        <add key="ClientID" value=""/>
        <add key="EmailAddress" value=""/>
        <add key="ClientSecret" value=""/>        
        <add key="RedirectURI" value=""/>      
    </appSettings>

    4. 创建MVC控制器OAuthController,并添加名为GoogleLogin的Action,用于重定向至Google页面进行登录。代码如下:

    public class OAuthController : Controller
    {
        public ActionResult GoogleLogin()
        {
            var url = "https://accounts.google.com/o/oauth2/auth?"+
                "scope={0}&state={1}&redirect_uri={2}&response_type=code&client_id={3}&approval_prompt=force";
            //userinfo.email表示获取用户的email
            var scope = HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.email");
            //对应于userinfo.email
            var state = "email";
            var redirectUri = HttpUtility.UrlEncode(ConfigurationManager.AppSettings["RedirectURI"]);
            var cilentId = HttpUtility.UrlEncode(ConfigurationManager.AppSettings["ClientID"]);
            return Redirect(string.Format(url, scope, state, redirectUri, cilentId));
        }
    }

    编译后,通过浏览器访问,假设域名是passport.cnblogs.cc,访问网址就是passport.cnblogs.cc/oauth/googlelogin,访问后,如果你的google帐户已经处于登录状态,则直接显示授权页面,如下图:

    点击"Allow access"之后,页面会被重定向回你的网站,我们这里重定向过来的网址是passport.cnblogs.cc/oauth2callback?state=email&code=4/BSCUqsaY6S5GYk9tFR-45-_UhL4-,查询参数code的值就是authorization code,接下来就是对这个重定向网址passport.cnblogs.cc/oauth2callback的处理(这个网址就是第1步中得到的Redirect URIs)。

    5. 在Global.asax.cs中添加路由规则,代码如下:

    routes.MapRoute(
        "oauth2callback",
        "oauth2callback",
        new { controller = "OAuth", action = "GoogleCallback", id = UrlParameter.Optional }
    );

    6. 在OAuthController中添加名为GoogleCallback的Action

    public class OAuthController : Controller
    {
        public ActionResult GoogleCallback()
        {
        }
    }

    接下来的操作都在GoogleCallback()中完成。

    7.  这一步是关键的地方,主要完成两个操作:

    a) 通过authorization code,向Google OAuth服务器请求access_token(访问令牌,每次调用Google API都需要这个)。
    b) 拿到access_token之后,调用Google API获取用户信息(这里是email)。

    主要参考文档:https://developers.google.com/accounts/docs/OAuth2WebServer

    7.1 根据authorization code获取access_token的代码流程是:

    • 向https://accounts.google.com/o/oauth2/token发送HTTP POST请求,并传递相应的参数。
    • 获取服务器的响应,响应内容的格式时json格式。
    • 将json反序列化为匿名类型的实例,并获取access_token。

    代码如下:

    //由于是https,这里必须要转换为HttpWebRequest
    var webRequest = WebRequest.Create("https://accounts.google.com/o/oauth2/token") as HttpWebRequest;
    webRequest.Method = "POST";
    webRequest.ContentType = "application/x-www-form-urlencoded";
    
    //参考https://developers.google.com/accounts/docs/OAuth2WebServer
    var postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}" +
        "&grant_type=authorization_code",
        Request.QueryString["code"],
            ConfigurationManager.AppSettings["ClientID"],
            ConfigurationManager.AppSettings["ClientSecret"],
            ConfigurationManager.AppSettings["RedirectURI"]);
    
    //在HTTP POST请求中传递参数
    using (var sw = new StreamWriter(webRequest.GetRequestStream()))
    {
        sw.Write(postData);
    }
    
    //发送请求,并获取服务器响应
    var resonseJson = "";
    using (var response = webRequest.GetResponse())
    {
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            resonseJson = sr.ReadToEnd();
        }
    }
    
    //通过Json.NET对服务器返回的json字符串进行反序列化,得到access_token
    var accessToken = JsonConvert.DeserializeAnonymousType(resonseJson, new { access_token = "" }).access_token;

    7.2 根据access_token读取用户信息的代码流程是:

    • 向https://www.googleapis.com/oauth2/v1/userinfo发送HTTP GET请求,在请求头中包含access_token信息。
    • 获取服务器的json格式的响应内容,并从中读取用户的email信息。

    代码如下:

    webRequest = WebRequest.Create("https://www.googleapis.com/oauth2/v1/userinfo") as HttpWebRequest;
    webRequest.Method = "GET";
    webRequest.Headers.Add("Authorization", "Bearer " + accessToken);
    
    using (var response = webRequest.GetResponse())
    {
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            return Content(JsonConvert.DeserializeAnonymousType(sr.ReadToEnd(), new { Email = "" }).Email);
        }
    }

    完整代码下载

    https://files.cnblogs.com/dudu/CNBlogsDemoMvcOAuth.rar 

  • 相关阅读:
    运算符、基本数据类型-----整型、字符串
    练习题
    python安装与初识(python起源、分类,if语句、while语句、基本数据类型、变量的命名)
    hdu2187悼念512汶川大地震遇难同胞——老人是真饿了(贪心 简单题)
    牛客小白月赛9 A签到(分数取模,逆元)
    牛客小白月赛9H论如何出一道水题(两个连续自然数互质)
    EOJ3134. 短信激活码(大数幂取模)
    EOJ3650 转机折扣(26进制,字符串)
    hdu1042 N!(大数求阶乘)
    hdu2061 Treasure the new start, freshmen!(暴力简单题)
  • 原文地址:https://www.cnblogs.com/dudu/p/asp_net_mvc_google_oauth_api.html
Copyright © 2020-2023  润新知