参考资料
https://www.cnblogs.com/Leo_wl/p/4919783.html
https://msdn.microsoft.com/zh-cn/library/microsoft.aspnet.identity.entityframework(v=vs.111).aspx
https://www.cnblogs.com/xsj1989/p/5287375.html
<connectionStrings>
<!--<add name="DefaultConnection" connectionString="Data Source=(LocalDb)MSSQLLocalDB;AttachDbFilename=|DataDirectory|aspnet-WebAPIDemo_UserLogin-20180327033757.mdf;Initial Catalog=aspnet-WebAPIDemo_UserLogin-20180327033757;Integrated Security=True"
providerName="System.Data.SqlClient" />-->
<add name="DefaultConnection" connectionString="Data Source=.SQL2008R2;User Id=sa;password=sa2008;Initial Catalog=AspNet_Identity;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Infrastructure;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using WebAPIDemo.Models;
//[assembly: OwinStartup(typeof(WebAPIDemo.Startup))]//删除Global.asax
namespace WebAPIDemo
{
public class Startup
{
public void Configuration(IAppBuilder app)//using Owin;
{
//var config = new HttpConfiguration();
//WebApiConfig.Register(config);
ConfigureOAuth(app);
//这一行代码必须放在ConfiureOAuth(app)之后
//app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()//using Microsoft.Owin.Security.OAuth
{
AllowInsecureHttp = true,//允许客户端一http协议请求;
TokenEndpointPath = new PathString("/token"),//using Microsoft.Owin; //token请求的地址,即http://localhost:端口号/token;
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(180),
Provider = new SimpleAuthorizationServerProvider(),//提供具体的认证策略
//refresh token provider
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
// 使应用程序可以使用不记名令牌来验证用户身份
//app.UseOAuthBearerTokens(OAuthOptions);//using Microsoft.AspNet.Identity.Owin
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
//开始 数据库操作EF CodeFirst生成数据库
public class AuthContext : IdentityDbContext<IdentityUser>
{
public AuthContext() : base("DefaultConnection")
{
}
public DbSet<RefreshToken> RefreshTokens { get; set; }
}
public class AuthRepository : IDisposable
{
private AuthContext _ctx;
private UserManager<IdentityUser> _userManager;
public AuthRepository()
{
_ctx = new AuthContext();
_userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx));
}
//注册用户
public async Task<IdentityResult> RegisterUser(RegisterModel userModel)
{
IdentityUser user = new IdentityUser
{
UserName = userModel.UserName
};
var result = await _userManager.CreateAsync(user, userModel.Password);
return result;
}
//查询用户
public async Task<IdentityUser> FindUser(string userName, string password)
{
IdentityUser user = await _userManager.FindAsync(userName, password);
return user;
}
public async Task<bool> AddRefreshToken(RefreshToken token)
{
var existingToken = _ctx.RefreshTokens.SingleOrDefault(r => r.Subject == token.Subject);
if (existingToken != null)
{
var result = await RemoveRefreshToken(existingToken);
}
_ctx.RefreshTokens.Add(token);
return await _ctx.SaveChangesAsync() > 0;
}
public async Task<bool> RemoveRefreshToken(int refreshTokenId)
{
var refreshToken = await _ctx.RefreshTokens.FindAsync(refreshTokenId);
if (refreshToken != null)
{
_ctx.RefreshTokens.Remove(refreshToken);
return await _ctx.SaveChangesAsync() > 0;
}
return false;
}
public async Task<bool> RemoveRefreshToken(RefreshToken refreshToken)
{
_ctx.RefreshTokens.Remove(refreshToken);
return await _ctx.SaveChangesAsync() > 0;
}
public async Task<RefreshToken> FindRefreshToken(int refreshTokenId)
{
var refreshToken = await _ctx.RefreshTokens.FindAsync(refreshTokenId);
return refreshToken;
}
public void Dispose()
{
_ctx.Dispose();
_userManager.Dispose();
}
}
//结束 数据库操作
//开始 token验证和刷新
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = await _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "用户名或密码不正确.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
identity.AddClaim(new Claim("sub", context.UserName));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"as:client_id", context.ClientId ?? string.Empty
},
{
"userName", context.UserName
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
}
public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var refreshTokenId = Guid.NewGuid().ToString("n");
using (AuthRepository _repo = new AuthRepository())
{
var token = new RefreshToken()
{
Id = refreshTokenId.GetHashCode(),
Subject = context.Ticket.Identity.Name,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddMinutes(30)
};
context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;
token.ProtectedTicket = context.SerializeTicket();
var result = await _repo.AddRefreshToken(token);
if (result)
{
context.SetToken(refreshTokenId);
}
}
}
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
int hashedTokenId = context.Token.GetHashCode();
using (AuthRepository _repo = new AuthRepository())
{
var refreshToken = await _repo.FindRefreshToken(hashedTokenId);
if (refreshToken != null)
{
//Get protectedTicket from refreshToken class
context.DeserializeTicket(refreshToken.ProtectedTicket);
var result = await _repo.RemoveRefreshToken(hashedTokenId);
}
}
}
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
}
public class RefreshToken
{
public int Id { get; set; }
public string Subject { get; set; }
public DateTime IssuedUtc { get; set; }
public DateTime ExpiresUtc { get; set; }
public string ProtectedTicket { get; set; }
};
//结束 token验证和刷新
}
//测试postman
//注册http://localhost:37351/api/account/Register body-raw-json
//{
//"UserName":"fingal@qq.com",
//"Password":"123456*",
//"ConfirmPassword":"123456*"
//}
//token http://localhost:37351/token body-x-www-form-urlencoded-key-value
//grant_type:password
//userName:fingal@qq.com
//password:123456*
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using WebAPIDemo.Models;
namespace WebAPIDemo.Controllers
{
//[EnableCors(origins: "*", headers: "*", methods: "*")]
//[Authorize(Users = "Alice,Bob")]//特殊用户限制
//[Authorize(Roles = "Administrators")]//角色限制
[Authorize]
[RoutePrefix("api/Account")]//http://localhost:38627/api/account/register
public class AccountController : ApiController
{
AuthRepository auth = new AuthRepository();
// POST api/Account/Register
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await auth.RegisterUser(model);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
private IHttpActionResult GetErrorResult(IdentityResult result)
{
if (result == null)
{
return InternalServerError();
}
if (!result.Succeeded)
{
if (result.Errors != null)
{
foreach (string error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
if (ModelState.IsValid)
{
// 没有可发送的 ModelState 错误,因此仅返回空 BadRequest。
return BadRequest();
}
return BadRequest(ModelState);
}
return null;
}
// GET api/Account/UserInfo
//[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UserInfo")]
public string GetUserInfo()
{
return User.Identity.GetUserName();
}
[Authorize]
[Route("")]
public List<Order> Get()
{
return Order.CreateOrders();
}
}
}