首先到http://open.weibo.com/development 注册一个开发者账号。

然后可以点微连接--网站接入

会分配App Key 和App Secret

然后点高级信息

在这里设置回调地址

这里的回调地址不能用localhost,后面再说怎么来设置这个

新建web项目

为了方便调试,在项目属性的Web中选择本地IIS

保存会提示创建虚拟目录

注意:如果是用本地IIS的话,需要把数据库连接改下,不能用程序自带的LocalDB

运行即可看到页面

此时需要请出一款神器:ngrok

下载后解压,命令行到解压目录,运行

ngrok -config=ngrok.cfg -subdomain mywebapp 

在浏览器访问:http://mywebapp.tunnel.qydev.com/MyWebApp/

好了,这个时候再来设置回调地址:

修改Views--Account 下的_ExternalLoginsListPartial.cshtml

@model MyWebApp.Models.ExternalLoginListViewModel
@using Microsoft.Owin.Security

<h4>使用其他服务登录。</h4>
<hr />
@{
    using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl }))
    {
        @Html.AntiForgeryToken()
        <div id="socialLoginList">
            <p>
                <button type="submit" class="btn btn-default" id="" name="provider" value="" title="使用你的 微博 帐户登录">微博登录</button>
            </p>
        </div>
    }
}

修改AccountController--ExternalLogin

public ActionResult ExternalLogin(string provider, string returnUrl)
        {
            // 请求重定向到外部登录提供程序
            string url = "https://api.weibo.com/oauth2/authorize?client_id=xxx&response_type=code&redirect_uri=http://mywebapp.tunnel.qydev.com/MyWebApp/Account/ExternalLoginCallback";
            return Redirect(url);
            //return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        }

这里的client_id就是上面微博分配的App Key

修改ExternalLoginCallback

public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            string appKey = "app key";
            string appSecret = "app secret";
            string code = Request["code"];
            string url = string.Format("https://api.weibo.com/oauth2/access_token");
            string callBack = "http://mvctest.tunnel.qydev.com/MvcWebApp/Account/ExternalLoginCallback";

            NameValueCollection collection = new NameValueCollection();
            collection.Add("client_id", appKey);
            collection.Add("client_secret", appSecret);
            collection.Add("grant_type", "authorization_code");
            collection.Add("code", code);
            collection.Add("redirect_uri", callBack);
            try
            {
                using (WebClient client = new WebClient())
                {
                    client.Encoding = Encoding.UTF8;
                    byte[] response = client.UploadValues(url, collection);
                    var returnStr = Encoding.UTF8.GetString(response);
                    OAuthEntity oauth = JsonConvert.DeserializeObject<OAuthEntity>(returnStr);
                    //获取用户信息
                    string userUrl = string.Format("https://api.weibo.com/2/users/show.json?access_token={0}&uid={1}", oauth.access_token, oauth.uid);
                    var userInfo = client.DownloadString(userUrl);
                    SinaUser sinaUser = JsonConvert.DeserializeObject<SinaUser>(userInfo);
                    UserLoginInfo login = new UserLoginInfo("sina", sinaUser.name);
                    var appUser = await UserManager.FindAsync(login);
                    if (appUser != null)
                    {
                        await SignInManager.SignInAsync(appUser, isPersistent: false, rememberBrowser: false);
                        if (string.IsNullOrEmpty(returnUrl))
                        {
                            return RedirectToAction("Index", "Home");
                        }
                        return RedirectToLocal(returnUrl);
                    }
                    else
                    {
                        ViewBag.ReturnUrl = returnUrl;
                        ViewBag.LoginProvider = "sina";
                        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = sinaUser.name + "@myweb.com", UserName = sinaUser.screen_name });
                    }
                }
            }
            catch (Exception ex)
            {
                return RedirectToAction("Login");
            }
        }

需要注意的是请求token必须是用Post,而且callBack必须和回调地址一致。

因为新浪微博用户信息没有返回邮箱,所以这里随便加了个@myweb.com

return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = sinaUser.name + "@myweb.com", UserName = sinaUser.screen_name });

否则后面注册的时候验证Email不通过。

这里添加了两个类,用来接收token和用户信息,直接放到AccountViewModels里面。

public class OAuthEntity
    {
        public string access_token { get; set; }
        public string remind_in { get; set; }
        public long expires_in { get; set; }
        public string uid { get; set; }
    }
    public class SinaUser
    {
        /// <summary>
        /// 用户UID
        /// </summary>
        public long id { get; set; }
        /// <summary>
        /// 用户昵称
        /// </summary>
        public string screen_name { get; set; }
        /// <summary>
        /// 友好显示名称
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 性别,m:男、f:女、n:未知
        /// </summary>
        public string gender { get; set; }
        /// <summary>
        /// 用户创建(注册)时间
        /// </summary>
        public string created_at { get; set; }
        /// <summary>
        /// 用户头像地址(中图),50×50像素
        /// </summary>
        public string profile_image_url { get; set; }
        /// <summary>
        /// 用户头像地址(大图),180×180像素
        /// </summary>
        public string avatar_large { get; set; }
        /// <summary>
        /// 用户头像地址(高清),高清头像原图
        /// </summary>
        public string avatar_hd { get; set; }
    }

修改添加一个用户名

public class ExternalLoginConfirmationViewModel
    {

        [Display(Name = "电子邮件")]
        public string Email { get; set; }
        /// <summary>
        /// 用户名
        /// </summary>
        [Display(Name = "用户名")]
        public string UserName { get; set; }
    }

修改ExternalLoginConfirmation

public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
        {
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Index", "Manage");
            }

            if (ModelState.IsValid)
            {
                // 从外部登录提供程序获取有关用户的信息
                UserLoginInfo info = new UserLoginInfo("sina", model.UserName);
                var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
                var result = await UserManager.CreateAsync(user);
                if (result.Succeeded)
                {
                    result = await UserManager.AddLoginAsync(user.Id, info);
                    if (result.Succeeded)
                    {
                        await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                        return RedirectToLocal(returnUrl);
                    }
                }
                AddErrors(result);
            }

            ViewBag.ReturnUrl = returnUrl;
            return View(model);
        }

修改下ExternalLoginConfirmation.cshtml页面

@model MyWebApp.Models.ExternalLoginConfirmationViewModel
@{
    ViewBag.Title = "注册";
}
<h2>@ViewBag.Title。</h2>
<h3>关联你的 @ViewBag.LoginProvider 帐户。</h3>

@using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

    <h4>关联表单</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <p class="text-info">
        你已成功使用 <strong>@ViewBag.LoginProvider</strong> 进行身份验证。
        请在下面输入此站点的用户名,然后单击“注册”按钮完成
        登录。
    </p>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
        </div>
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="注册" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

准备完毕了,运行,点击登录

这里就有微博登录了,先不着急用微博登录,先注册新用户,让程序把库建好

成功后会自动登录

看看ASP.Net Identity 通过 EF CodeFirst建的表

接下来试试微博登录,先注销当前账户,再点击登录,这次点击微博登录

会跳转到微博认证

登录后会跳转回来并带有code

http://mywebapp.tunnel.qydev.com/MyWebApp/Account/ExternalLoginCallback?code=dde370ced7025b82572fbe9b29ae5a6d

在后台通过调用token接口获取token后再获取用户信息

如果用户没有注册过,跳转到注册页面

注册后自动登录

此时可以看看表里的变化

AspNetUsers表:

[AspNetUserLogins]表:

再次登录就不用注册了。

Identity的表也可以方便扩展,比如给AspNetUsers添加一个[DisplayName]字段

首先开启EF Codefirst 的自动迁移

Enable-Migrations –EnableAutomaticMigrations

会生成一个目录和一个Configuration文件

然后执行

Add-Migration Init

再执行

Update-Database

也可以加上-v 查看具体的sql

之后在ApplicationUser类里面添加DisplayName

在注册的控制器里添加

更新注册页面

更新RegisterViewModel类

再次运行

update-database -v

之后重新注册

注册成功后看数据库

ASP.NET MVC网站使用新浪微博账号登录的更多相关文章

  1. 在Windows Azure上创建ASP.NET MVC网站

    本篇体验在Windows Azure上创建ASP.NET MVC网站. →登录到Windows Azure管理门户 →点击左下方的"新建" →点击"自定义创建" ...

  2. 关于linux asp.net MVC网站中 httpHandlers配置无效的处理方法

    近期有Jexus用户反映,在Linux ASP.NET MVC网站的Web.config中添加 httpHandlers 配置用于处理自定义类型,但是在运行中并没有产生预期的效果,服务器返回了404( ...

  3. ASP.NET MVC 网站开发总结(三) ——图片截图上传

    本着简洁直接,我们就直奔主题吧,这里需要使用到一个网页在线截图插件imgareaselect(请自行下载). 前台页面: <!DOCTYPE html> <html> < ...

  4. Asp.net MVC网站的基本结构

    Asp.net MVC网站的基本结构:Controller->IBLL(定义业务接口)->BLL->DA(调用Utility)->数据库 ,其中A->B表示A调用B 1. ...

  5. 总结一下ASP.NET MVC 网站的部署问题

    总结一下ASP.NET MVC 网站的部署问题 近日,准备把MVC建了一个新的测试站点部署到IIS上面,结果没想到出现了一系列的问题和错误,准备记录一下. 第一个问题,就是如何将MVC的站点部署到II ...

  6. IIS部署asp.net mvc网站

    iis配置简单的ASP.NET MVC网站编译器:VS 2013本地IIS:IIS 7操作系统:win 7MVC版本:ASP.NET MVC4sql server版本: 2008 r2 打开VS 20 ...

  7. 阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅

    做了多年的Web开发工作,网站部署也不在话下,可每次部署却并不是十分顺利,将本次在阿里云服务器上部署asp.net mvc网站遇到的问题记录如下. 平台是阿里云ECS,操作系统是 Windows Se ...

  8. 用网站(WebSite而不是WebProject)项目构建ASP.NET MVC网站

    从ASP.NET MVC第一个版本开始到现在,创建ASP.NET MVC项目的官方方法只有一个,“文件”->“新建”->“项目”,然后选择ASP.NET MVC X Web应用程序. 这种 ...

  9. 【转载】Asp.Net MVC网站提交富文本HTML标签内容抛出异常

    今天开发一个ASP.NET MVC网站时,有个页面使用到了FCKEditor富文本编辑器,通过Post方式提交内容时候抛出异常,仔细分析后得出应该是服务器阻止了带有HTML标签内容的提交操作,ASP. ...

随机推荐

  1. 解决Linux下IDEA无法使用ibus输入法的问题和tip乱码

    一:可以先按网上的配置/etc/profile里的输入法的一些参数,我是先配置了这些参数的,但是输入法还是没用,后来一直没管它了,今天用了一些方式可以了但不敢保证不需要先配置那些参数: 二:情况:开启 ...

  2. 1.2.4注意Sysyem.out.println与i--

    package com.cky.thread; /** * Created by chenkaiyang on 2017/11/27. */ public class MyThreadThird ex ...

  3. (单调队列) Bad Hair Day -- POJ -- 3250

    http://poj.org/problem?id=3250 Bad Hair Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

  4. python_运算符与表达式

    运算符与表达式 python运算符 运算符 功能说明 + 算术加法,列表.元组.字符串合并与连接,正号 - 算术减法,集合差集,相反数 * 算术乘法,序列重复 / 真除法 // 求整商,但如果操作数中 ...

  5. power designer简单教程

    1.file->new model 2.根据菜单或功能模型新建physical diagram(当然也可以新建package) 选中项目,右键——>new ->physical di ...

  6. 迁移桌面程序到MS Store(7)——APPX + Service

    本篇我们以一个Sample工程,来说明如何把一个常见结构的desktop application,转制成APPX并在MS Store提供下载. 之前的篇章中,我们已经介绍了一些内容,包括如何通过Vis ...

  7. DataFrame 操作

    # 删除td数据框中的 指定列 td.drop(columns=['ship-city'],axis=1,inplace=True) #删除指定列 并且修改掉原始数据 # 删除td数据框中的 最后一列 ...

  8. MongoDB 无法创建抽象类的问题,

     无法创建抽象类BsonClassMap.RegisterClassMap 大家都知道抽象类是无法实例化的,即:不能new. 在以下这些情况会遇到这种问题: 1.基类是抽象类: 2.基类是接口: 由于 ...

  9. C# Winform下一个热插拔的MIS/MRP/ERP框架(简介)

    Programmer普弱哥们都喜欢玩自己的框架,我也不例外. 理想中,这个框架要易于理解.易于扩展.易于维护:最重要的,易于CODING. 系统是1主体框架+N模组的多个EXE/DLL组成的,在主体框 ...

  10. collections, time, queue的应用

    collections  (克来克深思) Counter from collections import Counter # 引入模块, 计数器 Counter(康特) s = 'sadfasdfas ...