POST https://xxx.com/token HTTP/1.1Content-type:application/x-www-form-urlencodedAuthorization Basic Base64(clientId:clientSecret)username=irving&password=123456&grant_type=password
POST http://localhost:19923/tokenContent-Type: Application/x-www-form-
urlencodedAuthorization Basic Base64(clientId:clientSecret)username=irving&password=123456&grant_type=refresh_token
备注: 有了前面相关token,服务调用也很简单
GET https://xxx.com/api/v1/account/profile HTTP/1.1Content-type:application/x-www-form-urlencodedAuthorization Authorization: Bearer {THE TOKEN}
WebApi Startup
get access_token
在 C# 中用 HttpClient 实现一个简单的客户端,代码如下:
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace Tdf.OAuthClientTest
{
public class OAuthClientTest
{
private HttpClient _httpClient;
public OAuthClientTest()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromMinutes(30);
_httpClient.BaseAddress = new Uri("http://localhost:13719");
}
public void Get_Accesss_Token_By_Client_Credentials_Grant()
{
var parameters = new Dictionary();
parameters.Add("UserName", "Bobby");
parameters.Add("Password", "123");
parameters.Add("grant_type", "password");
Console.WriteLine(_httpClient.PostAsync("/token", new FormUrlEncodedContent(parameters))
.Result.Content.ReadAsStringAsync().Result);
}
}
}
这样,运行客户端程序就可以拿到 Access Token 了。
refresh_token
在 C# 中用 HttpClient 实现一个简单的客户端,代码如下:
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace Tdf.OAuthClientTest
{
public class OAuthClientTest
{
private HttpClient _httpClient;
public OAuthClientTest()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromMinutes(30);
_httpClient.BaseAddress = new Uri("http://localhost:13719");
}
public void Get_Accesss_Token_By_Client_Credentials_Grant()
{
var parameters = new Dictionary();
// refresh_token
parameters.Add("grant_type", "refresh_token");
parameters.Add("refresh_token", "DAB1FE2B-2F84-4534-A620-F6B9B474B503");
Console.WriteLine(_httpClient.PostAsync("/token", new FormUrlEncodedContent(parameters))
.Result.Content.ReadAsStringAsync().Result);
}
}
}
这样,运行客户端程序就可以拿到 Access Token 了。
OWIN WEBAPI
默认Startup.Auth.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Microsoft.Owin.Security.OAuth;
using Owin;
using Ems.Web.Providers;
using Ems.Web.Models;
namespace Ems.Web
{
///
/// Startup
///
public partial class Startup
{
///
/// OAuthOptions
///
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
///
/// PublicClientId
///
public static string PublicClientId { get; private set; }
///
/// ConfigureAuth
/// 有关配置身份验证的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=301864
///
///
public void ConfigureAuth(IAppBuilder app)
{
// 将数据库上下文和用户管理器配置为对每个请求使用单个实例
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
// 使应用程序可以使用 Cookie 来存储已登录用户的信息
// 并使用 Cookie 来临时存储有关使用第三方登录提供程序登录的用户的信息
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// 针对基于 OAuth 的流配置应用程序
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
//在生产模式下设 AllowInsecureHttp = false
AllowInsecureHttp = true
};
// 使应用程序可以使用不记名令牌来验证用户身份
app.UseOAuthBearerTokens(OAuthOptions);
// 取消注释以下行可允许使用第三方登录提供程序登录
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
}
}
}
Startup.cs
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Practices.Unity;
using Owin;
using System;
using System.Web.Http;
using Tdf.Application.Act.UserMgr;
using Tdf.Utils.Config;
using Tdf.WebApi.Providers;
using Unity.WebApi;
[assembly: OwinStartup(typeof(Tdf.WebApi.Startup))]
namespace Tdf.WebApi
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
var config = new HttpConfiguration();
WebApiConfig.Register(config);
IUnityContainer container = UnityConfig.GetConfiguredContainer();
config.DependencyResolver = new UnityDependencyResolver(container);
ConfigureOAuth(app, container);
// 这一行代码必须放在ConfiureOAuth(app)之后
// Microsoft.AspNet.WebApi.Owin
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app, IUnityContainer container)
{
IUserAppService userService = container.Resolve();
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
#if DEBUG
AllowInsecureHttp = true,
#endif
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(double.Parse(ConfigHelper.GetValue("TokenExpireMinute", "120"))),
RefreshTokenProvider = new TdfRefreshTokenProvider(userService),
Provider = new TdfAuthorizationServerProvider(userService)
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
var opts = new OAuthBearerAuthenticationOptions()
{
Provider = new TdfOAuthBearerProvider("Token")
};
app.UseOAuthBearerAuthentication(opts);
}
}
}
TdfAuthorizationServerProvider.cs
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Tdf.Application.Act.UserMgr;
using Tdf.Application.Act.UserMgr.Dtos;
using Tdf.Domain.Act.Entities;
namespace Tdf.WebApi.Providers
{
///
/// Resource Owner Password Credentials Grant 授权
///
public class TdfAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
///
/// Password Grant 授权服务
///
readonly IUserAppService _userService;
///
/// 构造函数
///
/// Password Grant 授权服务
public TdfAuthorizationServerProvider(IUserAppService userService)
{
this._userService = userService;
}
///
/// Resource Owner Password Credentials Grant 的授权方式;
/// 验证用户名与密码 [Resource Owner Password Credentials Grant[username与password]|grant_type=password&username=irving&password=654321]
/// 重载 OAuthAuthorizationServerProvider.GrantResourceOwnerCredentials() 方法即可
///
///
///
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var user = await _userService.Login(new LoginInput() { UserName = context.UserName, Password = context.Password });
var userInfo = user.Result as User;
if (user.ErrCode != 0 || userInfo == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
else
{
// 验证context.UserName与context.Password
// 调用后台的登录服务验证用户名与密码
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, userInfo.Id.ToString()));
oAuthIdentity.AddClaim(new Claim("UserId", userInfo.Id.ToString()));
oAuthIdentity.AddClaim(new Claim("UserName", userInfo.UserName));
var props = new AuthenticationProperties(new Dictionary {
{ "user_id", userInfo.Id.ToString() },
{ "user_name", userInfo.UserName }
});
var ticket = new AuthenticationTicket(oAuthIdentity, props);
context.Validated(ticket);
await base.GrantResourceOwnerCredentials(context);
}
}
///
/// 把Context中的属性加入到token中
///
///
///
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult
TdfRefreshTokenProvider.cs
using Microsoft.Owin.Security.Infrastructure;
using System;
using System.Threading.Tasks;
using Tdf.Application.Act.UserMgr;
using Tdf.Domain.Act.Entities;
using Tdf.Utils.Config;
using Tdf.Utils.GuidHelper;
namespace Tdf.WebApi.Providers
{
///
/// 刷新Token
/// 生成与验证Token
///
public class TdfRefreshTokenProvider : AuthenticationTokenProvider
{
///
/// 授权服务
///
private IUserAppService _userService;
///
/// 构造函数
///
/// 授权服务
public TdfRefreshTokenProvider(IUserAppService userService)
{
this._userService = userService;
}
///
/// 创建refreshToken
///
/// 上下文
///
public override async Task CreateAsync(AuthenticationTokenCreateContext context)
{
if (string.IsNullOrEmpty(context.Ticket.Identity.Name)) return;
var refreshTokenLifeTime = ConfigHelper.GetValue("TokenExpireMinute", "120");
if (string.IsNullOrEmpty(refreshTokenLifeTime)) return;
// generate access token
var refreshTokenId = new RegularGuidGenerator().Create();
context.Ticket.Properties.IssuedUtc = DateTime.UtcNow;
context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddMinutes(double.Parse(refreshTokenLifeTime));
var refreshToken = new RefreshToken()
{
Id = refreshTokenId,
UserId = new Guid(context.Ticket.Identity.Name),
IssuedUtc = DateTime.Parse(context.Ticket.Properties.IssuedUtc.ToString()),
ExpiresUtc = DateTime.Parse(context.Ticket.Properties.ExpiresUtc.ToString()),
ProtectedTicket = context.SerializeTicket()
};
// Token没有过期的情况强行刷新,删除老的Token保存新的Token
var jsonMsg = await _userService.SaveTokenAsync(refreshToken);
if (jsonMsg.ErrCode == 0)
{
context.SetToken(refreshTokenId.ToString());
}
}
///
/// 刷新refreshToken[刷新access token时,refresh token也会重新生成]
///
/// 上下文
///
public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
var jsonMsg = await _userService.GetToken(context.Token);
if (jsonMsg.ErrCode == 0)
{
var refreshToken = jsonMsg.Result as RefreshToken;
if (refreshToken != null)
{
context.DeserializeTicket(refreshToken.ProtectedTicket);
await _userService.RemoveToken(context.Token);
}
}
}
}
}
TdfOAuthBearerProvider.cs
using Microsoft.Owin.Security.OAuth;
using System.Threading.Tasks;
namespace Tdf.WebApi.Providers
{
public class TdfOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
readonly string _name;
public TdfOAuthBearerProvider(string name)
{
_name = name;
}
public override Task RequestToken(OAuthRequestTokenContext context)
{
var value = context.Request.Query.Get(_name);
if (!string.IsNullOrEmpty(value))
{
context.Token = value;
}
return Task.FromResult(null);
}
}
}
结合 ASP.NET 现有的安全机制,借助 OWIN 的威力,Microsoft.Owin.Security.OAuth 的确让开发基于 OAuth 的 Web API 变得更简单。
public class ReverseWords {
/**
* 题目:颠倒一个句子中的词的顺序。比如: I am a student颠倒后变成:student a am I.词以空格分隔。
* 要求:
* 1.实现速度最快,移动最少
* 2.不能使用String的方法如split,indexOf等等。
* 解答:两次翻转。
*/
publ
oracle外部表是只允许只读访问,不能进行DML操作,不能创建索引,可以对外部表进行的查询,连接,排序,创建视图和创建同义词操作。
you can select, join, or sort external table data. You can also create views and synonyms for external tables. Ho
发现一个老外写的不错的jquery插件,可以实现将HTML
表格导出为excel,pdf等格式,
地址在:
https://github.com/kayalshri/
下面看个例子,实现导出表格到excel,pdf
<html>
<head>
<title>Export html table to excel an