public Task <IActionResult> Challenge(string provider, string returnUrl) { if (string.IsNullOrEmpty(returnUrl)) { returnUrl = "~/"; } // validate returnUrl - either it is a valid OIDC URL or back to a local page if (Url.IsLocalUrl(returnUrl) == false) { // user might have clicked on a malicious link - should be logged throw ApiException.Common(RequestLocalizer["Invalid return URL"]); } // start challenge and roundtrip the return URL and scheme var props = new AuthenticationProperties { RedirectUri = Url.Action(nameof(Callback)), //RedirectUri = returnUrl, Items = { { "returnUrl", returnUrl }, { "scheme", provider }, } }; return(Task.FromResult((IActionResult)Challenge(props, provider))); }
public ApiResult <bool> ChangePassword(RequestPassword model) { IUser user; switch (model.Type) { case 0: user = ApplicationUser.FindByName(model.UserName); CheckUser(user); if (user.Password != model.OldPassword.MD5()) { throw ApiException.Common(RequestLocalizer["The old password is incorrect"]); } break; case 1: user = ApplicationUser.FindByMobile(model.Mobile); CheckUser(user); if (!CheckVerCode(model.InternationalAreaCode + model.Mobile, model.VerCode, 0)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } if (user.Mobile != model.Mobile) { throw ApiException.Common(RequestLocalizer["Incorrect mobile phone number"]); } break; case 2: user = ApplicationUser.FindByMail(model.Mail); CheckUser(user); if (!CheckVerCode(model.Mail, model.VerCode, 1)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } if (user.Mail != model.Mail) { throw ApiException.Common(RequestLocalizer["Incorrect email address"]); } break; default: throw ApiException.Common("Type类型不正确!"); } void CheckUser(IUser u) { if (u == null) { throw ApiException.Common(RequestLocalizer["The user was not found"]); } } user.Password = model.NewPassword; user.Save(); return(ApiResult.Ok(true)); }
public async Task Handle(ExternalSignInContext externalSignInContext) { var properties = externalSignInContext.AuthenticationProperties; var clientFactory = externalSignInContext.HttpClientFactory; var requestLocalizer = externalSignInContext.RequestLocalizer; var externalSignInHandler = externalSignInContext.Context; var user = externalSignInContext.User; var requestServices = externalSignInContext.RequestServices; var providerKey = properties.Items["providerKey"]; // 首先获取OpenId var openIdEndpoint = QueryHelpers.AddQueryString(QQDefaults.OpenIdEndpoint, "access_token", providerKey); var backchannel = clientFactory.CreateClient(); var openIdResponse = await backchannel.GetAsync(openIdEndpoint); var openIdContent = await openIdResponse.Content.ReadAsStringAsync(); openIdContent = openIdContent.TrimStart("callback( ").TrimEnd(" );\n"); var openIdPayload = JObject.Parse(openIdContent); // 存储openid,绑定到系统的用户,作为系统在第三方的唯一标识 var openId = openIdPayload["openid"].Value <string>(); var clientId = openIdPayload["client_id"].Value <string>(); var tokenRequestParameters = new Dictionary <string, string>() { { "access_token", providerKey }, { "oauth_consumer_key", clientId }, { "openid", openId }, }; var endpoint = QueryHelpers.AddQueryString(QQDefaults.UserInformationEndpoint, tokenRequestParameters); var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint); requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await backchannel.SendAsync(requestMessage); var userInfoPayload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); var ret = userInfoPayload.RootElement.GetString("ret").ToInt(); if (ret < 0) { throw ApiException.Common(requestLocalizer[userInfoPayload.RootElement.GetString("msg")]); } var options = requestServices.GetRequiredService <IOptionsMonitor <QQOptions> >().CurrentValue; var identity = user.Identity as ClaimsIdentity; externalSignInHandler.RunClaimActions(options.ClaimActions, identity, userInfoPayload.RootElement); identity?.AddClaim(new Claim(OAuthSignInAuthenticationDefaults.Sub, openId)); }
public virtual async Task <SignInResult> LoginAsync(IUser user, string password, bool rememberMe = false) { if (!(user is TUser u)) { throw ApiException.Common(_requestLocalizer["The user was not found"]); } var result = await _signInManager.PasswordSignInAsync(u, password, rememberMe, false); return(result); }
public virtual async Task <SignInResult> LoginAsync(IUser user) { if (!(user is TUser u)) { throw ApiException.Common(_requestLocalizer["The user was not found"]); } await _signInManager.SignInAsync(u, false); return(SignInResult.Success); }
/// <summary> /// 获取过期时间 /// </summary> /// <param name="token"></param> /// <returns></returns> private DateTime GetExpire(string token) { token = token.Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase); var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token); var exp = jwtToken.Claims.FirstOrDefault(f => f.Type == "exp"); if (exp == null) { throw ApiException.Common(_requestLocalizer["Could not find the exp claim in token"], 500); } var d = new DateTime(1970, 1, 1, 0, 0, 0, DateTime.Now.Kind).AddSeconds(exp.Value.ToInt()); return(d); }
public virtual Task DeleteAccountAsync(IUser user) { XTrace.WriteLine($"删除用户信息:{(user as TUser)}"); if (user == null || user.ID < 1) { throw ApiException.Common(_requestLocalizer["The user was not found"]); } (user as TUser)?.Delete(); var ucs = UserConnect.FindAllByUserID(user.ID); ucs.Delete(); return(Task.CompletedTask); }
public ApiResult <ResponseUserInfo> GetUserInfo() { //var principal = User; var identity = User.Identity as IUser; if (identity == null) { throw ApiException.Common(RequestLocalizer["User type error"], 500); } var data = new ResponseUserInfo(); data.Copy(identity, false, "Roles"); data.SetRoles(identity.Roles); return(ApiResult.Ok(data)); }
protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { // 认证之前检查Cookie中是否携带Token,有则设置头部的Authorization var authorization = "Authorization"; if (!Request.Headers.ContainsKey(authorization) && Request.Cookies.TryGetValue("Admin-Token", out var token)) { Request.Headers.Add(authorization, token); } else { token = Request.Headers[authorization]; } if (token.IsNullOrWhiteSpace()) { return(AuthenticateResult.NoResult()); } var uc = CheckLocalRecord(token); if (uc != null) { return(uc.Expire < DateTime.Now ? AuthenticateResult.Fail(_requestLocalizer["No login or login timeout"]) : GetAuthenticateResult(uc)); } // 登录记录不存在,请求授权中心 var result = await Authenticate(token); if (result == null) { XTrace.WriteLine("请求授权中心失败"); throw ApiException.Common("Request authorization center failed", 500); } if (result.Status != 0) { XTrace.WriteLine($"IAM中心请求认证结果异常:{result.ToJson()}"); throw ApiException.Common(result.Msg, result.Status); } XTrace.WriteLine($"IAM中心请求认证后本地记录:{result.ToJson()}\\s\ntoken: {token}"); return(await LocalSignIn(result.Data, token)); }
public override ApiResult <string> Post(ApplicationUser value) { var exists = ApplicationUser.FindByName(value.Name) != null; if (exists) { throw ApiException.Common(RequestLocalizer["User already exists"]); } // 新增账号默认密码123456 if (value.Password.IsNullOrWhiteSpace()) { value.Password = "******".MD5(); } return(base.Post(value)); }
public ApiResult <string> UnbindOAuth([FromQuery] string id) { var uc = UserConnect.FindByKey(id); if (uc == null) { throw ApiException.Common(RequestLocalizer["Data not found"]); } if (!IsSupperAdmin && uc.UserID != AppUser.ID) { throw ApiException.Common(RequestLocalizer["No permission"]); } uc.Delete(); return(ApiResult.Ok()); }
/// <summary> /// 处理请求参数 /// </summary> /// <param name="context"></param> /// <returns></returns> protected async Task HandleRequestAsync(HttpContext context) { SetAuthorization(context); var req = context.Request; var restRequest = new RestRequest(Path, DataFormat.Json); if (Enum.TryParse(req.Method, true, out Method method)) { restRequest.Method = method; } if (req.Query.Any()) { foreach (var(key, value) in req.Query) { restRequest.AddQueryParameter(key, value); } } if (req.ContentLength != null) { var b = new byte[req.ContentLength.Value]; var total = await req.Body.ReadAsync(b); var s = Encoding.UTF8.GetString(b); if (!s.IsNullOrWhiteSpace()) { Body = JObject.Parse(s); restRequest.AddJsonBody(Body); } } RestResponse = await _restClient.ExecuteAsync(restRequest); // 判断是否有异常 if (RestResponse.ErrorException != null) { XTrace.WriteException(RestResponse.ErrorException); throw ApiException.Common("The IAM Server is not available", 500); } }
/// <summary> /// 向IAM中心请求认证 /// </summary> /// <param name="token"></param> /// <returns></returns> private async Task <ApiResult <ResponseUserInfo> > Authenticate(string token) { var restClient = new RestClient(Options.Url); restClient.AddDefaultHeader("Authorization", token); var path = "/api/Account/GetUserInfo"; var restRequest = new RestRequest(path); var restResponse = await restClient.ExecuteAsync(restRequest); if (restResponse.StatusCode != HttpStatusCode.OK) { XTrace.WriteLine(restResponse.Content.ToJson()); throw ApiException.Common(_requestLocalizer["Server error"], 500); } var result = JsonConvert.DeserializeObject <ApiResult <ResponseUserInfo> >(restResponse.Content); return(result); }
/// <summary> /// 更新用户信息 /// </summary> /// <param name="dic"></param> /// <returns></returns> public virtual async Task UpdateAsync(IDictionary <string, object> dic) { var user = new TUser(); foreach (var(key, value) in dic) { if (value == null) { continue; // 空值表示不改变 } user.SetItem(key, value); } var result = await _userManager.UpdateAsync(user); if (!result.Succeeded) { throw ApiException.Common(_requestLocalizer[result.Errors.ToArray()[0].Code]); } }
private async Task SaveToken(string content) { var jwtTokenResult = JsonConvert.DeserializeObject <ApiResult <JwtToken> >(content); if (jwtTokenResult.Status != 0) { throw ApiException.Common(jwtTokenResult.Msg); } var jwtToken = jwtTokenResult.Data; var idp = "IdentityServer4"; var userInfo = jwtToken.UserInfo; if (userInfo == null) { throw ApiException.Common("登录返回的UserInfo不能为空", 500); } var u = await UpdateUserAsync(userInfo); var uc = UserConnect.FindByProviderAndOpenID(idp, userInfo.Name) ?? new UserConnect { Provider = idp, UserID = u.ID, OpenID = userInfo.Name, LinkID = userInfo.ID.ToInt(), Enable = true }; uc.AccessToken = jwtToken.Token; uc.Avatar = userInfo.Avatar; uc.NickName = userInfo.DisplayName; uc.Expire = jwtToken.Expires ?? GetExpire(jwtToken.Token); // 下面这两个防止uc没有删除导致再次注册时,id换了但还是以前的记录 uc.UserID = u.ID; uc.LinkID = userInfo.ID.ToInt(); uc.Save(); }
public async Task <ApiResult <string> > Error(string errorId) { // retrieve error details from identityserver var message = await _interaction.GetErrorContextAsync(errorId); if (message != null) { if (!_environment.IsDevelopment()) { // only show in development message.ErrorDescription = null; } XTrace.WriteLine($"授权出错:{message.Error}。描述:{message.ErrorDescription}"); throw ApiException.Common(message.Error, 402); } else { return(ApiResult <string> .Ok("没有错误,但是跳到了'/home/error'这里")); } }
public async Task <ApiResult <bool> > UpdateUserInfo(RequestUserInfo userInfo) { if (userInfo.ID < 1) { throw ApiException.Common(RequestLocalizer["Incorrect ID"]); } var u = AppUser; if (IsSupperAdmin || u.ID == userInfo.ID) { userInfo.ID = u.ID; userInfo.Name = u.Name; await _userService.UpdateAsync(userInfo.ToDictionary()); } else { throw ApiException.Common(RequestLocalizer["No permission"]); } return(ApiResult.Ok(true)); }
public async Task <ApiResult <JwtToken> > Login(RequestRegister model, [FromQuery] string culture) { IUser user; Microsoft.AspNetCore.Identity.SignInResult result; switch (model.Type) { case 1: user = await _userService.FindByPhoneNumberAsync(model.Mobile); result = await _userService.LoginAsync(user, model.Password); break; case 2: if (!CheckVerCode(model.InternationalAreaCode + model.Mobile, model.VerCode, 0)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } user = await _userService.FindByPhoneNumberAsync(model.Mobile); result = await _userService.LoginAsync(user); break; case 3: user = await _userService.FindByEmailAsync(model.Mail); result = await _userService.LoginAsync(user, model.Password); break; case 4: if (!CheckVerCode(model.Mail, model.VerCode, 1)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } user = await _userService.FindByEmailAsync(model.Mail); result = await _userService.LoginAsync(user); break; case 0: default: user = await _userService.FindByNameAsync(model.UserName); result = await _userService.LoginAsync(user, model.Password); break; } if (result.Succeeded) { var jwtToken = HttpContext.Features.Get <JwtToken>(); return(ApiResult.Ok(jwtToken)); } throw ApiException.Common(RequestLocalizer["Wrong account or password"]); }
/// <summary> /// 获取或创建用户 /// </summary> /// <returns></returns> private async Task <IManageUser> GetOrCreateUserAsync(ClaimsPrincipal user, AuthenticationProperties properties) { var options = Options; var provider = properties.Items["scheme"]; var openid = user.FindFirstValue(OAuthSignInAuthenticationDefaults.Sub); var uc = UserConnect.FindByProviderAndOpenID(provider, openid); IManageUser appUser; if (uc == null) { if (!options.CreateUserOnOAuthLogin) { throw ApiException.Common("用户不存在,请联系管理员"); } uc = new UserConnect() { Provider = provider, OpenID = openid, Enable = true }; uc.Fill(user); appUser = new ApplicationUser { Name = Guid.NewGuid().ToString().Substring(0, 8), Enable = true, RoleID = 4 }; // 角色id 4 为游客 // 此处可改用本系统服务替换,去除ApplicationUser依赖 var result = await _userManager.CreateAsync(appUser as ApplicationUser, "123456"); if (!result.Succeeded) { throw ApiException.Common($"创建用户失败:{result.Errors.First().Description}"); } uc.UserID = appUser.ID; } else { appUser = await _userManager.FindByIdAsync(uc.UserID.ToString()); } if (!appUser.Enable) { throw ApiException.Common($"用户已被禁用"); } // 填充用户信息 Fill(appUser, user); if (appUser is IAuthUser user3) { user3.Logins++; user3.LastLogin = DateTime.Now; user3.LastLoginIP = Request.Host.Host; user3.Save(); } try { uc.Save(); } catch (Exception ex) { //为了防止某些特殊数据导致的无法正常登录,把所有异常记录到日志当中。忽略错误 XTrace.WriteException(ex); } return(appUser); }
/// <summary> /// 获取或创建用户 /// </summary> /// <returns></returns> public virtual async Task <IManageUser> GetOrCreateUserAsync(ClaimsPrincipal user, AuthenticationProperties properties, bool createUserOnOAuthLogin) { var provider = properties.Items["scheme"]; var openid = user.FindFirstValue(OAuthSignInAuthenticationDefaults.Sub); var uc = UserConnect.FindByProviderAndOpenID(provider, openid); IManageUser appUser; if (uc == null) { if (!createUserOnOAuthLogin) { throw ApiException.Common(_requestLocalizer["The user does not exist, please contact the administrator"]); } uc = new UserConnect() { Provider = provider, OpenID = openid, Enable = true }; uc.Fill(user); appUser = new TUser { Name = Guid.NewGuid().ToString().Substring(0, 8), Enable = true, RoleID = 4 }; // 角色id 4 为游客 // 通过第三方登录创建的用户设置随机密码 var result = await _userManager.CreateAsync((TUser)appUser, Guid.NewGuid().ToString().Substring(0, 8)); if (!result.Succeeded) { throw ApiException.Common($"{_requestLocalizer["Failed to create user"]}:{_requestLocalizer[result.Errors.First().Description]}"); } uc.UserID = appUser.ID; } else { appUser = await _userManager.FindByIdAsync(uc.UserID.ToString()) as IManageUser; } if (appUser == null) { throw ApiException.Common(_requestLocalizer["The user was not found"]); } if (!appUser.Enable) { throw ApiException.Common(_requestLocalizer["The user has been disabled"]); } // 填充用户信息 Fill(appUser, user); if (appUser is IAuthUser user3) { user3.Logins++; user3.LastLogin = DateTime.Now; //user3.LastLoginIP = Request.Host.Host; user3.Save(); } try { uc.Save(); } catch (Exception ex) { //为了防止某些特殊数据导致的无法正常登录,把所有异常记录到日志当中。忽略错误 XTrace.WriteException(ex); } return(appUser); }
bool SetPrincipal(AuthorizationFilterContext actionContext) { var context = actionContext.HttpContext; var requestLocalizer = context.RequestServices.GetRequiredService <IStringLocalizer <Request> >(); var userService = (actionContext.HttpContext.RequestServices.GetRequiredService(typeof(IUserService)) as IUserService) ?? throw ApiException.Common(requestLocalizer["IUserService is not registered"], 500); if (!context.User.Identity.IsAuthenticated) { return(false); } var id = context.User.FindFirst(JwtRegisteredClaimNames.NameId)?.Value; if (id == null) { id = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; } if (id == null) { id = context.User.FindFirst(JwtRegisteredClaimNames.Sub)?.Value; } if (id == null) { XTrace.WriteLine("context.User中找不到存放id的声明"); throw new ApiException(500, requestLocalizer["Could not find the id claim in context.User"]); } var user = userService.FindByIdAsync(id).Result; if (user == null) { return(false); } var ac = user; ////将搜索到的AccessToken映射到IIdentity,用户名,权限role var iid = (IIdentity)ac; // 角色列表 var up = new GenericPrincipal(iid, new[] { iid.AuthenticationType }); context.Features[typeof(IUser)] = iid as IUser; context.User = up; Thread.CurrentPrincipal = up; return(true); }
public async Task <ApiResult <string> > Register(RequestRegister model, [FromQuery] string culture) { string[] names; object[] values; switch (model.Type) { case 1: case 2: if (!CheckVerCode(model.InternationalAreaCode + model.Mobile, model.VerCode, 0)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } names = new[] { nameof(IUser.Name), nameof(IUser.DisplayName), nameof(IUser.Mobile), nameof(IUser.Password), }; // 模式2,不带密码,默认密码由内部生成,应用应该引导用户修改密码后使用 values = new object[] { model.Mobile, model.Mobile, model.Mobile, model.Password }; break; case 3: case 4: if (!CheckVerCode(model.Mail, model.VerCode, 1)) { throw ApiException.Common(RequestLocalizer["The verification code is incorrect or expired"]); } names = new[] { nameof(IUser.Name), nameof(IUser.DisplayName), nameof(IUser.Mail), nameof(IUser.Password), }; values = new object[] { model.Mail, model.Mail, model.Mail, model.Password }; break; case 0: default: names = new[] { nameof(IUser.Name), nameof(IUser.DisplayName), nameof(IUser.Password), }; values = new object[] { model.UserName, model.UserName, model.Password }; break; } var result = await _userService.CreateAsync(names, values); if (result.Succeeded) { return(ApiResult.Ok()); } var err = result.Errors.ToArray()[0]; XTrace.WriteLine($"创建用户发生错误:{err.Description}"); throw ApiException.Common(RequestLocalizer[err.Code]); }