using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using MrHuo.OAuth.Github; using MrHuo.OAuth.Microsoft; using System.IdentityModel.Tokens.Jwt; using System.Management; using System.Security.Claims; using System.Text; namespace asg_form.Controllers { [ApiController] public class OAuthController : Controller { private readonly RoleManager roleManager; private readonly UserManager userManager; public OAuthController( RoleManager roleManager, UserManager userManager) { this.roleManager = roleManager; this.userManager = userManager; } [HttpGet("oauth/setpassword")] public async Task SetPasswordAsync(string username,string password, [FromServices] IOptions jwtOptions) { var user = await userManager.FindByNameAsync(username); await userManager.AddPasswordAsync(user, password); var claims = new List(); claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())); claims.Add(new Claim(ClaimTypes.Name, user.UserName)); var roles = await userManager.GetRolesAsync(user); foreach (string role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } string jwtToken = BuildToken(claims, jwtOptions.Value); return jwtToken; } [HttpGet("oauth/{type}")] public IActionResult Index( string type,string recall, [FromServices] GithubOAuth githubOAuth, [FromServices] MicrosoftOAuth microsoftOAuth ) { var redirectUrl = ""; switch (type.ToLower()) { case "github": { redirectUrl = githubOAuth.GetAuthorizeUrl(); break; } case "microsoft": { redirectUrl = microsoftOAuth.GetAuthorizeUrl(); break; } default: return NotFound($"没有实现【{type}】登录方式!"); } return Redirect(redirectUrl); } private static string BuildToken(IEnumerable claims, JWTOptions options) { DateTime expires = DateTime.Now.AddSeconds(options.ExpireSeconds); byte[] keyBytes = Encoding.UTF8.GetBytes(options.SigningKey); var secKey = new SymmetricSecurityKey(keyBytes); var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature); var tokenDescriptor = new JwtSecurityToken(expires: expires, signingCredentials: credentials, claims: claims); return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor); } [HttpGet("oauth/{type}callback")] public async Task LoginCallback( string type, [FromServices] GithubOAuth githubOAuth, [FromServices] MicrosoftOAuth microsoftOAuth, [FromServices] IOptions jwtOptions, [FromQuery] string code, [FromQuery] string state) { try { switch (type.ToLower()) { case "github": { var authorizeResult = await githubOAuth.AuthorizeCallback(code, state); if (!authorizeResult.IsSccess) { throw new Exception(authorizeResult.ErrorMessage); } var userinfo = await githubOAuth.GetUserInfoAsync(authorizeResult.AccessToken); //如果该Gitgub用户不存在,则创建一个 var user = new User() { Id=20,UserName = $"gh{userinfo.Name}", Email = userinfo.Email }; if (user == null) { var user_new = await userManager.FindByNameAsync(userinfo.Name); var r = await userManager.CreateAsync(user); return Redirect($"https://commentary.idvasg.cn/oauth/next?username=gh{userinfo.Name}"); } var claims = new List(); claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())); claims.Add(new Claim(ClaimTypes.Name, user.UserName)); var roles = await userManager.GetRolesAsync(user); foreach (string role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } string jwtToken = BuildToken(claims, jwtOptions.Value); return Redirect($"https://commentary.idvasg.cn/oauth/loginok?token={jwtToken}"); break; } case "microsoft": { var authorizeResult = await microsoftOAuth.AuthorizeCallback(code, state); if (!authorizeResult.IsSccess) { throw new Exception(authorizeResult.ErrorMessage); } var userinfo = await githubOAuth.GetUserInfoAsync(authorizeResult.AccessToken); var user = new User() { Id = 20, UserName = $"ms{userinfo.Name}", Email = userinfo.Email }; if (user == null) { var user_new = await userManager.FindByNameAsync(userinfo.Name); var r = await userManager.CreateAsync(user); return Redirect($"https://commentary.idvasg.cn/oauth/next?username=gh{userinfo.Name}"); } var claims = new List(); claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())); claims.Add(new Claim(ClaimTypes.Name, user.UserName)); var roles = await userManager.GetRolesAsync(user); foreach (string role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } string jwtToken = BuildToken(claims, jwtOptions.Value); return Redirect($"https://commentary.idvasg.cn/oauth/loginok?token={jwtToken}"); break; } default: throw new Exception($"没有实现【{type}】登录回调!"); } } catch (Exception ex) { return Content(ex.Message); } } } }