IdentityServer4使用asp.net核心

时间:2018-06-19 08:37:43

标签: asp.net-core jwt identityserver4

我在asp.net核心中使用IdentityServer4使用密码授权请求JWT /访问承载令牌,但我似乎无法找到正确的方法。

以下是我注册用户的POST请求。

  

http://localhost:52718/account/register

以下是使用IdentityServer4从中获取JWT令牌的承载令牌GET请求

  

http://localhost:52718/connect/token

以下是我登录用户的POST请求

  

http://localhost:52718/account/signin

现在,我正在尝试做的是当我登录我的用户时,我想要一个JWT / Bearer Token,就像我从http://localhost:52718/connect/token获得的那样。当我点击此网址时。

enter image description here

这是我的AccountController代码:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Server.Models;
using Server.Models.AccountViewModels;
using Server.Models.UserViewModels;

namespace Server.Controllers
{
    public class AccountController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public AccountController(
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager
            )
        {
            _userManager = userManager;
            _roleManager = roleManager;
        }

        [HttpPost]
        public async Task<IActionResult> Register([FromBody]RegisterViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new ApplicationUser { UserName = model.UserName, FirstName = model.FirstName, LastName = model.LastName, Email = model.Email };

            var result = await _userManager.CreateAsync(user, model.Password);

            string role = "Basic User";

            if (result.Succeeded)
            {
                if (await _roleManager.FindByNameAsync(role) == null)
                {
                    await _roleManager.CreateAsync(new IdentityRole(role));
                }
                await _userManager.AddToRoleAsync(user, role);
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("userName", user.UserName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("firstName", user.FirstName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("lastName", user.LastName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("email", user.Email));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("role", role));

                return Ok(new ProfileViewModel(user));
            }

            return BadRequest(result.Errors);


        }

        public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var result = await _userManager.FindByNameAsync(model.UserName);

            if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
            {
                return Ok(new ProfileViewModel(result));
            }

            return BadRequest("Invalid username or password.");
        }
    }
}

当我点击signin方法时,我成功获取了用户的数据。

enter image description here

但是当用户登录我的应用程序时,我还需要一个jwt / access令牌。

现在我的实际问题是:

我的登录方法可以做什么,所以当用户登录时,它会返回令牌以及其他用户数据。我希望我简要解释一下我的问题。

谢谢

1 个答案:

答案 0 :(得分:0)

我找到了自己的问题的答案。在开始之前,我向您展示我在定义客户端的那个代码。

public static IEnumerable<Client> GetClients()
{
        // client credentials client
    return new List<Client>
    {

        // resource owner password grant client
        new Client
        {
            ClientId = "ro.angular",
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.Address,
                "api1"
            }
        }
    };
}

现在我在登录方法中要做的就是使用TokenClient类来请求令牌。要创建实例,您需要传递令牌端点地址,客户端ID和密码。

接下来,我使用Requesting a token using the password grant允许客户端将用户名和密码发送到令牌服务,并获得代表该用户的访问令牌。

这是我需要修改的登录代码:

public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
{
    var disco = await DiscoveryClient.GetAsync("http://localhost:52718");
    if (disco.IsError)
    {
        return BadRequest(disco.Error);
    }

    var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.angular", "secret");
    var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.UserName, model.Password, "api1 openid");

    if (tokenResponse.IsError)
    {
        return BadRequest(tokenResponse.Error);
    }

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = _userManager.FindByNameAsync(model.UserName);

    var result = await _userManager.FindByNameAsync(model.UserName);

    if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
    {
        return Ok(new ProfileViewModel(result, tokenResponse));
    }

        return BadRequest("Invalid username or password.");
}

我还修改了ProfileViewModel类,并添加了两个新的令牌和到期日:

public class ProfileViewModel
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }

    public string Token { get; set; }

    public int Expiry { get; set; }

    public ProfileViewModel()
    {

    }

    public ProfileViewModel(ApplicationUser user, TokenResponse UToken = null)
    {
        Id = user.Id;
        FirstName = user.FirstName;
        LastName = user.LastName;
        Email = user.Email;
        Token = UToken.AccessToken;
        Expiry = UToken.ExpiresIn;
    }

    public static IEnumerable<ProfileViewModel> GetUserProfiles(IEnumerable<ApplicationUser> users)
    {
        var profiles = new List<ProfileViewModel> { };
        foreach (ApplicationUser user in users)
        {
            profiles.Add(new ProfileViewModel(user));
        }

        return profiles;
    }
}

现在这是我的愿望输出。希望这个答案可以帮助其他人。

enter image description here