应用客户端增加上传ClientId,应用在线和配置在线以ClientId作为唯一标识
大石头 authored at 2021-12-18 00:58:57
3.06 KiB
Stardust
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NewLife;
using NewLife.Web;
using Stardust.Data;
using Stardust.Server.Common;
using Stardust.Server.Models;
using Stardust.Server.Services;

namespace Stardust.Server.Controllers
{
    /// <summary>OAuth服务。向应用提供验证服务</summary>
    [Route("[controller]/[action]")]
    public class OAuthController : ControllerBase
    {
        /// <summary>用户主机</summary>
        public String UserHost => HttpContext.GetUserHost();

        private readonly TokenService _service;
        public OAuthController(TokenService appService) => _service = appService;

        [ApiFilter]
        public TokenModel Token([FromBody] TokenInModel model)
        {
            var set = Setting.Current;

            if (model.grant_type.IsNullOrEmpty()) model.grant_type = "password";

            var ip = HttpContext.GetUserHost();
            var clientId = model.ClientId;

            // 密码模式
            if (model.grant_type == "password")
            {
                var app = _service.Authorize(model.UserName, model.Password, set.AutoRegister);

                // 更新应用信息
                app.LastLogin = DateTime.Now;
                app.LastIP = ip;
                app.SaveAsync();

                app.WriteHistory("Authorize", true, model.UserName, UserHost);

                var tokenModel = _service.IssueToken(app.Name, set.TokenSecret, set.TokenExpire, clientId);

                AppOnline.UpdateOnline(app, clientId, ip, tokenModel.AccessToken);

                return tokenModel;
            }
            // 刷新令牌
            else if (model.grant_type == "refresh_token")
            {
                var (jwt, ex) = _service.DecodeToken(model.refresh_token, set.TokenSecret);

                // 验证应用
                var app = App.FindByName(jwt?.Subject);
                if ((app == null || !app.Enable) && ex == null) ex = new InvalidOperationException($"无效应用[{jwt.Subject}]");

                if (ex != null)
                {
                    app.WriteHistory("RefreshToken", false, ex.ToString(), UserHost);
                    throw ex;
                }

                if (clientId.IsNullOrEmpty()) clientId = jwt.Id;

                app.WriteHistory("RefreshToken", true, model.refresh_token, UserHost);

                var tokenModel = _service.IssueToken(app.Name, set.TokenSecret, set.TokenExpire, clientId);

                AppOnline.UpdateOnline(app, clientId, ip, tokenModel.AccessToken);

                return tokenModel;
            }
            else
            {
                throw new NotSupportedException($"未支持 grant_type={model.grant_type}");
            }
        }

        [ApiFilter]
        public Object UserInfo(String token)
        {
            var set = Setting.Current;

            var app = _service.DecodeToken(token, set);
            return new
            {
                app.Id,
                app.Name,
                app.DisplayName,
                app.Category,
            };
        }
    }
}