首页 文章

IdentityServer4使用asp.net核心中的密码授权请求JWT /访问承载令牌

提问于
浏览
0

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

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

http:// localhost:52718 / account / register

下面是承载令牌GET请求,我可以使用IdentityServer4从中获取JWT令牌

http:// localhost:52718 / connect / token

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

http:// localhost:52718 / account / signin

现在,我要做的是当我登录我的用户然后我想要一个JWT / Bearer Token,就像我从这里得到的那样http://localhost:52718/connect/token . 当我点击这个URL .

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.");
        }
    }
}

当我点击登录方法时,我成功获取了用户的数据 .

enter image description here

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

现在我的实际问题是:

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

谢谢

1 回答

  • 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"
                }
            }
        };
    }
    

    现在我在Signin方法中做的是使用TokenClient类来请求令牌 . 要创建实例,您需要传递令牌 endpoints 地址,客户端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类并添加了两个新的Token&Expiry:

    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

相关问题