172 lines
7.2 KiB
C#
172 lines
7.2 KiB
C#
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
|
||
{
|
||
|
||
|
||
|
||
public class OAuthController : Controller
|
||
{
|
||
|
||
private readonly RoleManager<Role> roleManager;
|
||
private readonly UserManager<User> userManager;
|
||
|
||
public OAuthController(
|
||
RoleManager<Role> roleManager, UserManager<User> userManager)
|
||
{
|
||
|
||
this.roleManager = roleManager;
|
||
this.userManager = userManager;
|
||
}
|
||
|
||
|
||
|
||
|
||
[HttpGet("oauth/setpassword")]
|
||
public async Task<object> SetPasswordAsync(string username,string password, [FromServices] IOptions<JWTOptions> jwtOptions)
|
||
{
|
||
var user = await userManager.FindByNameAsync(username);
|
||
await userManager.AddPasswordAsync(user, password);
|
||
var claims = new List<Claim>();
|
||
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<Claim> 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<IActionResult> LoginCallback(
|
||
string type,
|
||
[FromServices] GithubOAuth githubOAuth,
|
||
[FromServices] MicrosoftOAuth microsoftOAuth,
|
||
[FromServices] IOptions<JWTOptions> 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<Claim>();
|
||
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<Claim>();
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|