WebApi-Identity 角色建立和管理
其實Identity要使用角色這部份,微軟也都幫我們想好了,接著就開始實作吧,先在Infrastructure新增下面類別
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace identityDemo.Infrastructure
{
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
var appRoleManager = new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
return appRoleManager;
}
}
}
接著是把Startup.cs裡面的ConfigureOAuthTokenGeneration改成如下
private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
// 配置此db context 和 user manager去使用single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
// Plugin the OAuth Token產生和消耗將在此
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat("http://localhost:59822")
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
在BaspApiController新增如下片段
private ApplicationRoleManager _AppRoleManager = null;
protected ApplicationRoleManager AppRoleManager
{
get
{
return _AppRoleManager ?? Request.GetOwinContext().GetUserManager<ApplicationRoleManager>();
}
}
在Models新增如下類別
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace identityDemo.Models
{
public class CreateRoleBindingModel
{
[Required]
[StringLength(256, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
[Display(Name = "Role Name")]
public string Name { get; set; }
}
public class UsersInRoleModel
{
public string Id { get; set; }
public List<string> EnrolledUsers { get; set; }
public List<string> RemovedUsers { get; set; }
}
}
打開ModelFactory.cs,在類別裡面新增如下方法
public RoleReturnModel Create(IdentityRole appRole)
{
return new RoleReturnModel
{
Url = _UrlHelper.Link("GetRoleById", new { id = appRole.Id }),
Id = appRole.Id,
Name = appRole.Name
};
}
然後新增如下類別,在ModelFactory.cs的底下
public class RoleReturnModel
{
public string Url { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
在Controllers新增如下Web api
using identityDemo.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
namespace identityDemo.Controllers
{
[Authorize(Roles = "Admin")]
[RoutePrefix("api/roles")]
public class RolesController : BaseApiController
{
[Route("{id:guid}", Name = "GetRoleById")]
public async Task<IHttpActionResult> GetRole(string Id)
{
var role = await this.AppRoleManager.FindByIdAsync(Id);
if (role != null)
{
return Ok(TheModelFactory.Create(role));
}
return NotFound();
}
[Route("", Name = "GetAllRoles")]
public IHttpActionResult GetAllRoles()
{
var roles = this.AppRoleManager.Roles;
return Ok(roles);
}
[Route("create")]
public async Task<IHttpActionResult> Create(CreateRoleBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var role = new IdentityRole { Name = model.Name };
var result = await this.AppRoleManager.CreateAsync(role);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
Uri locationHeader = new Uri(Url.Link("GetRoleById", new { id = role.Id }));
return Created(locationHeader, TheModelFactory.Create(role));
}
[Route("{id:guid}")]
public async Task<IHttpActionResult> DeleteRole(string Id)
{
var role = await this.AppRoleManager.FindByIdAsync(Id);
if (role != null)
{
IdentityResult result = await this.AppRoleManager.DeleteAsync(role);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
return NotFound();
}
[Route("ManageUsersInRole")]
public async Task<IHttpActionResult> ManageUsersInRole(UsersInRoleModel model)
{
var role = await this.AppRoleManager.FindByIdAsync(model.Id);
if (role == null)
{
ModelState.AddModelError("", "Role does not exist");
return BadRequest(ModelState);
}
foreach (string user in model.EnrolledUsers)
{
var appUser = await this.AppUserManager.FindByIdAsync(user);
if (appUser == null)
{
ModelState.AddModelError("", String.Format("User: {0} does not exists", user));
continue;
}
if (!this.AppUserManager.IsInRole(user, role.Name))
{
IdentityResult result = await this.AppUserManager.AddToRoleAsync(user, role.Name);
if (!result.Succeeded)
{
ModelState.AddModelError("", String.Format("User: {0} could not be added to role", user));
}
}
}
foreach (string user in model.RemovedUsers)
{
var appUser = await this.AppUserManager.FindByIdAsync(user);
if (appUser == null)
{
ModelState.AddModelError("", String.Format("User: {0} does not exists", user));
continue;
}
IdentityResult result = await this.AppUserManager.RemoveFromRoleAsync(user, role.Name);
if (!result.Succeeded)
{
ModelState.AddModelError("", String.Format("User: {0} could not be removed from role", user));
}
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
[Route("user/{id:guid}/roles")]
[HttpPut]
public async Task<IHttpActionResult> AssignRolesToUser([FromUri] string id, [FromBody] string[] rolesToAssign)
{
var appUser = await this.AppUserManager.FindByIdAsync(id);
if (appUser == null)
{
return NotFound();
}
var currentRoles = await this.AppUserManager.GetRolesAsync(appUser.Id);
var rolesNotExists = rolesToAssign.Except(this.AppRoleManager.Roles.Select(x => x.Name)).ToArray();
if (rolesNotExists.Count() > 0)
{
ModelState.AddModelError("", string.Format("Roles '{0}' does not exixts in the system", string.Join(",", rolesNotExists)));
return BadRequest(ModelState);
}
IdentityResult removeResult = await this.AppUserManager.RemoveFromRolesAsync(appUser.Id, currentRoles.ToArray());
if (!removeResult.Succeeded)
{
ModelState.AddModelError("", "Failed to remove user roles");
return BadRequest(ModelState);
}
IdentityResult addResult = await this.AppUserManager.AddToRolesAsync(appUser.Id, rolesToAssign);
if (!addResult.Succeeded)
{
ModelState.AddModelError("", "Failed to add user roles");
return BadRequest(ModelState);
}
return Ok();
}
}
}
把原本的AccountsController的一些action一樣改成只限Admin可訪問,比如得到所有使用者的權限,接著我想要使用code first的方式,修改目前我的帳號加進admin裡面,打開migrations>Configuration,把程式碼改成如下,帳號請設定成您自己的,在下面這段除了新增帳號新增三種角色,我同時把目前我自己的帳號加進兩種角色裡面。
namespace identityDemo.Migrations
{
using identityDemo.Infrastructure;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<identityDemo.Infrastructure.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(identityDemo.Infrastructure.ApplicationDbContext context)
{
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var user = new ApplicationUser()
{
UserName = "SuperPowerUser",
Email = "taiseer.joudeh@gmail.com",
EmailConfirmed = true,
FirstName = "Taiseer",
LastName = "Joudeh",
Level = 1,
JoinDate = DateTime.Now.AddYears(-3)
};
manager.Create(user, "MySuperP@ss!");
if (roleManager.Roles.Count() == 0)
{
roleManager.Create(new IdentityRole { Name = "SuperAdmin" });
roleManager.Create(new IdentityRole { Name = "Admin" });
roleManager.Create(new IdentityRole { Name = "User" });
}
var adminUser = manager.FindByName("SuperPowerUser");
var kinanson = manager.FindByName("kinanson");
manager.AddToRoles(adminUser.Id, new string[] { "SuperAdmin", "Admin" });
manager.AddToRoles(kinanson.Id, new string[] { "SuperAdmin", "Admin" });
}
}
}
以上再請多多指教囉。