代码改变世界

mvc webapi 授权demo

2018-03-31 16:39  FingalZhu  阅读(245)  评论(0编辑  收藏  举报

参考资料

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

image

<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();
         }
     }
}