abp new abpdemo --template app --ui none --separate-identity-server
IdentityServer4
提供了八个API
/.well-known/openid-configuration
/connect/authorize
/connect/token
/connect/userinfo
/connect/deviceauthorization
/connect/introspect
/connect/revocation
/connect/endsession
具体使用方式看官方文档的ENDPOINTS
部分,我就记录一些常用的
http://docs.identityserver.io/en/latest/
Welcome to IdentityServer4 (latest) — IdentityServer4 1.0.0 documentation
/api/account/login
只是验证登录,并不返回token
Abp中获取token的接口是/connect/token
参数是来自Body
的x-www-form-urlencoded
类型,不需要access_token
必要参数
{
grant_type : "password",
username : "admin",
password : "1q2w3E*",
client_id : "dbpdemo_App"
}
grant_type
根据数据库中的IdentityServerClientGrantTypes
表的GrantType
字段client_id
根据数据库中的IdentityServerClients
表的ClientId
字段注意点:
var dic = new Dictionary
{
{"client_id","Qzzx_Web"},
{"client_secret","1q2w3e*"},
{"grant_type","password"},
{"scope","Qzzx" }, //必须加上项目和数据库里定义得授权范围,否则登录成功后还是提示401
//{"grant_type","client_credentials"},
{"username",model.UserNameOrEmailAddress},
{"password",model.Password},
{"SaveTokens",true}
};
如数据库中:
如项目中:
//using EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Ms.Qzzx.CustomLogins.Dto;
using System.Security.Claims;
using System.Text;
using System;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Users;
using Org.BouncyCastle.Asn1.Crmf;
using static Volo.Abp.Identity.Settings.IdentitySettingNames;
using System.Reflection;
namespace Ms.Qzzx.CustomLogins
{
///
/// 自定义登录
///
public class CustomLoginAppService : QzzxAppService, ICustomLoginAppService
{
private SignInManager _signInManager;
protected IdentityUserManager _userManager;
private readonly IHttpClientFactory _httpClientFactory;
public CustomLoginAppService(IdentityUserManager userManager, IHttpClientFactory httpClientFactory,
SignInManager signInManager)
{
_userManager = userManager;
_httpClientFactory = httpClientFactory;
_signInManager = signInManager;
}
public async Task Authenticate([FromBody] AuthenticateModel model)
{
var AuthServer = "https://localhost:44351";
var client = _httpClientFactory.CreateClient(AuthServer);
client.BaseAddress = new Uri(AuthServer);
var dic = new Dictionary
{
{"client_id","Qzzx_Web"},
{"client_secret","1q2w3e*"},
{"grant_type","password"},
{"scope","Qzzx" }, //必须加上项目和数据库里定义得授权范围
//{"grant_type","client_credentials"},
{"username",model.UserNameOrEmailAddress},
{"password",model.Password},
{"SaveTokens",true}
};
//var dic = new Dictionary
// {
// {"client_id","Qzzx_App"},
// {"client_secret",""},
// {"grant_type","password"},
// //{"grant_type","client_credentials"},
// {"username",model.UserNameOrEmailAddress},
// {"password",model.Password},
// };
var dicStr = dic.Select(m => m.Key + "=" + m.Value).DefaultIfEmpty().Aggregate((m, n) => m + "&" + n);
HttpContent httpContent = new StringContent(dicStr);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var oauthRep = await client.PostAsync("connect/token", httpContent);
var oauthStr = await oauthRep.Content.ReadAsStringAsync();
var oauthResult = default(Id4TokenOutput);
if (oauthRep.IsSuccessStatusCode)
{
if (!string.IsNullOrEmpty(oauthStr))
oauthResult = JsonConvert.DeserializeObject(oauthStr);
}
else
{
if (string.IsNullOrEmpty(oauthStr) || oauthStr.Contains("error"))
throw new UserFriendlyException(oauthRep.ReasonPhrase);
}
//var loginResult = await GetLoginResultAsync(
// model.UserNameOrEmailAddress,
// model.Password,
// GetTenancyNameOrNull()
//);
//自定义登录获取结果
var result = await _signInManager.PasswordSignInAsync(model.UserNameOrEmailAddress, model.Password, true, true);
if (!result.Succeeded)
{
throw new UserFriendlyException("账号或者密码不正确!");
}
else if (result.IsLockedOut)
{
throw new UserFriendlyException("登录失败,该账户已被锁定!");
}
var tt = CurrentUser.UserName;
#region 注释
//var accessToken = await _userManager.GetAuthenticationTokenAsync(user, model.UserNameOrEmailAddress, "");
生成 JWT Token
//var tokenHandler = new JwtSecurityTokenHandler();
//var key = Encoding.ASCII.GetBytes();
//var tokenDescriptor = new SecurityTokenDescriptor
//{
// Subject = new ClaimsIdentity(new Claim[]
// {
// new Claim(ClaimTypes.Name, user.UserName)
// }),
// Expires = DateTime.UtcNow.AddDays(1),
// SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
//};
//var token = tokenHandler.CreateToken(tokenDescriptor);
//var encryptedToken = tokenHandler.WriteToken(token);
//var accessToken = CreateAccessToken(CreateJwtClaims(loginResult.Identity));
#endregion
var user = await _userManager.FindByNameAsync(model.UserNameOrEmailAddress);
return await BuildResult(user, oauthResult?.access_token, oauthResult.expires_in);
//return new AuthenticateResultModel
//{
// AccessToken = accessToken,
// EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
// ExpireInSeconds = 60 * 60 * 24,
// UserId = user.Id
//};
}
#region 私有方法
private async Task BuildResult(IdentityUser user, string token, int secord)
{
var roles = await _userManager.GetRolesAsync(user);
if (roles == null || roles.Count == 0) throw new UserFriendlyException("当前用户未分配角色");
return new AuthenticateResultModel
{
AccessToken = token,
//EncryptedAccessToken = GetEncryptedAccessToken(token),
ExpireInSeconds = secord,
UserId = user.Id
};
}
#endregion
}
}