WTM(ASP.NET Core)自定义身份认证系统配置第三方外部登录(github登录)

         使用WMT框架开发移动应用的过程中遇到了第三方登录的问题,于是我就自己给WTM应用添加了第三方登录。这里以github未例子。我参照了天上木有OvO大神的博客  SPA+.NET Core3.1 GitHub第三方授权登录 使用AspNet.Security.OAuth.GitHub。做了属于WTM框架的第三方登录扩展。

        一、GitHub授权登录前你必须获取client_id,client_secret如何获取和测试GitHub,请参照GitHub 第三方登录这篇博客。

       二、在appsettings.json添加配置信息

"Authentication": {
    "GitHub": {
      "ClientId": "d08c83abe14c9f4e20f8",
      "ClientSecret": "392b888c3926d4dd0cdb212829ec836d1eba41a2",
      "redirectUrlMobile": "http://localhost:8080/#/pages/withAccount/login-result",
      "redirectUrlPC": "https://localhost:5001/Login/LoginResult"
    }
  }

        三、在WTM项目的model层添加用户类WebUser继承自FrameworkUserBase,添加OpenID字段存储,第三方登录返回的openid一类的身份标识信息。并在DataAccess层数据库上下文进行注册。

/// <summary>
    /// 登录用户
    /// </summary>
    [Table("FrameworkUsers")]
    public class WebUser : FrameworkUserBase
    {
        [Display(Name = "部门名称")]
        [Required(ErrorMessage = "{0}是必填项")]
        public Guid UnitWorkID { get; set; }
        [Display(Name = "部门名称")]
        public UnitWork UnitWork { get; set; }
        /// <summary>
        /// 外部登录
        /// </summary>
        [Display(Name = "外部登录")]
        public string OpenID { get; set; }
    }

        四、添加AuthenticationApi控制器,将配置IConfiguration注入到控制器中,用来获取appsettings的配置信息。并添加相应的处理方法

 public class AuthenticationApiController : BaseApiController
 {

        private readonly IConfiguration _configuration;
        public AuthenticationApiController(IConfiguration configuration)
        {
            _configuration = configuration;
        }
 }

        五、添加ExternalLogin处理方法,识别是从手机端还是PCWEB端发起的外部登录请求,并携带client_id到github获取code值。

[HttpGet("~/ExternalLogin")]
        public IActionResult ExternalLogin(string provider, string terminal)
        {
            HttpContext.Session.SetString("terminal", terminal);
            switch (provider)
            {
                case ("github"):
                    return Redirect("https://github.com/login/oauth/authorize?client_id=d08c83abe14c9f4e20f8");
                default:
                    break;
            }
            return Content("参数错误");

        }

        六、添加SignIn方法,从github上获取access_token,并返回给SPA或者PCWEB的回调页面进行处理。

[HttpGet("~/signin-github")]
        public IActionResult SignIn(string code)
        {
            string terminal = HttpContext.Session.GetString("terminal");
            string redirectUrl = "";
            if (terminal == "mobile")
            {
                redirectUrl = _configuration["Authentication:GitHub:redirectUrlMobile"];
            }
            else
            {
                redirectUrl = _configuration["Authentication:GitHub:redirectUrlPC"];
            }
            string clientId = _configuration["Authentication:GitHub:ClientId"];
            string clientSecret = _configuration["Authentication:GitHub:ClientSecret"];
            //利用coede获取access_token
            string url = $"https://github.com/login/oauth/access_token?client_id={clientId}&client_secret={clientSecret}&code={code}";
            string re = HttpHelper.SendHttp("post", url);
            string[] reArr = re.Split("&");
            return Redirect(redirectUrl + "?acc=" + reArr[0]);
        }

        七、添加AutoLogin处理方法,根据前端回调页面发给后台的openid在WebUser 中扩展的openid字段中进行检索,如果没有则返回空值,让前端页面调到登录页进行注册。如果有则给SPA应用下发JWT Token,WTM MVC调用框架生成的DoLogin进行登录操作。

 

 [HttpPost]
        public async Task<IActionResult> AutoLogin(string openid)
        {
            var user = await DC.Set<WebUser>().AsNoTracking().SingleOrDefaultAsync(x => x.OpenID.Contains(openid));
            if (user == null)
            {
                var temp = new
                {
                    access_token = "no",
                    openid = openid
                };
                return Content(JsonConvert.SerializeObject(temp), "application/json");
            }
            LoginVM vm = CreateVM<LoginVM>();
            vm.ITCode = user.ITCode;
            vm.Password = user.Password;
            var userwtm = vm.DoLogin();
            LoginUserInfo = userwtm;
            string terminal = HttpContext.Session.GetString("terminal");
            if (terminal == "mobile")
            {
                var authService = HttpContext.RequestServices.GetService(typeof(ITokenService)) as ITokenService;
                var token = await authService.IssueTokenAsync(LoginUserInfo);
                return Content(JsonConvert.SerializeObject(token), "application/json");
            }
            else
            {
                AuthenticationProperties properties = null;
                properties = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(30))
                };
                var principal = LoginUserInfo.CreatePrincipal();
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, properties);
                return Redirect("/Home/");
            }
        }

        控制器业务逻辑就完成了,接下来,咱们分为别WTM MVC和SPA应用添加登录逻辑。

        八、WTM MVC登录

        1.1、在login视图中添加登录按钮  

<li>
              <div class="layui-row layui-col-space10" style="text-align:center">
                  <div class="layui-col-md4">
                    
                      <img src="~/images/WX.jpg" class="layui-nav-img">
                  </div>
                  <div class="layui-col-md4">
                      <img src="~/images/QQ.jpg" class="layui-nav-img">
                  </div>
                  <div class="layui-col-md4">
                      <img src="~/images/GITHUB.jpg" class="layui-nav-img" onclick="githublogin()">
                  </div>
              </div>
          </li>

       

         添加登录js方法

 function githublogin() {
          var url = window.location.href;
          var urlBase = url.replace('Login/Login', "");
          window.location.href = urlBase + 'ExternalLogin?provider=github&terminal=PC';
      }

          1.2、WTM MVC在login控制器中添加LoginResult方法,返回视图,作为WTM MVC的回调页面。


        [Public]
        public IActionResult LoginResult(string acc)
        {
            ViewBag.acc = acc;
            return View();
        }

@{
    Layout = null;
}

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="/layui/css/layui.css">
    <script src="/jquery.min.js"></script>
    <script src="/jquery.cookie.js"></script>
    <script src="/layui/layui.js"></script>
    <script src="/_js/framework_layui.js?time=@DateTime.Now.Ticks"></script>
    <link rel="stylesheet" href="~/sitecss/logincss.css">
    <title>WTM</title>
    <script type="text/javascript">
        $(document).ready(function () {
        //利用access_token获取openid,如果成功则调用后台AutoLogin方法,完成登录。
        $.ajax({
            url: 'https://api.github.com/user?' + '@ViewBag.acc',
            success: function (res) {
                var openid = res.login;
                autoLogin(openid);
            },
            error: function (xhr) {
                myFunction();
            },

        })
        });
        //发生错误弹出窗口
        function myFunction() {
            if (confirm("网络错误,稍后重试")) {
                window.location.href = "/Login/Login"
            } else {
                window.location.href = "/Login/Login"
            }
        }
        //调用后台AutoLogin
        function autoLogin(id) {
            $.ajax({
            url: '/api/AuthenticationApi/AutoLogin?openid='+id,
            type: 'post',
                success: function (res) {
                    console.log(res)

                if (res.access_token == 'no') {
                    window.location.href = '/Login/Reg';
                } else {
                    window.location.href = "/"
                }
            },
            error: function (xhr) {
                myFunction();
            },

        })
        };
    layui.use('layer');
    </script>
</head>

<body class="loginBody">
    <div class="loginDiv">
        <h4>
            登录中...
        </h4>

    </div>


</body>

</html>

       WTM MVC端完成设置。接下来我们继续这只SAP应用端。

       九、SAP应用端设置    

       1.1、在login.vue页面添加GitHubLogin方法,添加到你需要@click的按钮和图片上面

GitHubLogin(){
	const urlBase = this.Common.urlBase;
    //window.location.href = 'https://github.com/login/oauth/authorize?client_id=d08c83abe14c9f4e20f8';
	window.location.href = urlBase + "ExternalLogin?provider=github&terminal=mobile";
			}

       1.2、添加login-result页面,地址要和在appsettings.json文件中能对应上的地址。其中在onLoad中接收,后台返回的access_token,并在github请求openid发到后台autoLogin,并接收JWT Token。

<template>
	<view>
		<scroll-view scroll-y class="page">
			<view style="margin-top: 200px;">
				<view class="image-content" style="text-align: center; width: 100%;">
					<image style="width: 200px; height: 200px; background-color: #eeeeee;margin-top:100;" src="../../static/刷新.png"></image>
				</view>
				<view class="solids-bottom  flex align-center">
					<view class="flex-sub text-center">
						<view class="solid-bottom text-xl padding">
							<text class="text-black text-bold">登录中......</text>
						</view>

					</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
			}
		},
		onLoad(op) {
			console.log(op);
			const acc = op.acc;
			var that = this;

			uni.request({
				url: 'https://api.github.com/user?' + acc,
				success: (res) => {
					console.log(res.data);
					if (res.statusCode === 200) {
						let openid = res.data.login;
						that.autoLogin(openid);
					} else {
						uni.showModal({
							title: '提示',
							content: '网络问题,稍后重试',
							showCancel: false,
							success: function(res) {
								if (res.confirm) {
									uni.navigateTo({
										url: '../withAccount/Login'
									});
								}
							}
						});
					}
				},
				fail() {

					uni.showModal({
						title: '提示',
						content: '网络问题,稍后重试',
						showCancel: false,
						success: function(res) {
							if (res.confirm) {
								uni.navigateTo({
									url: '../withAccount/Login'
								});
							}
						}
					});
				}
			});
		},
		methods: {
			registered() {
				uni.navigateTo({
					url: '../withAccount/registered'
				})
			},
			autoLogin(id) {
				var that = this;
				console.log(id)
				const urlBase = this.Common.urlBase;
				uni.request({
					url: urlBase + "api/AuthenticationApi/AutoLogin?openid=" + id,
					method: "POST",
					success: (res) => {

						console.log(res.data);
						if (res.statusCode === 200) {
							let access_token = res.data.access_token;
							if (access_token === 'no') {
								that.registered();
							} else {
								uni.setStorageSync('access_token', res.data.access_token);
								uni.setStorageSync('refresh_token', res.data.refresh_token);
								uni.showToast({
									title: '登录成功',
									duration: 2000,
									icon: 'none',
									success() {
										uni.navigateTo({
											url: '../withAccount/testlist'
										});
									}
								});
							}
						} else {
							uni.showToast({
								title: '登录失败',
								duration: 2000,
								icon: 'none',
								success() {
									uni.navigateTo({
										url: '../withAccount/Login'
									});
								}
							});
						}
					}
				});
			}
		}
	}
</script>
<style>

</style>

       就此,完成了github扩展登录。值得一提的是,WTM里很有很多好东西是文档里没写的,例如咱们这里用的JWT令牌生成。

var authService = HttpContext.RequestServices.GetService(typeof(ITokenService)) as ITokenService;
var token = await authService.IssueTokenAsync(LoginUserInfo);

       只需要简单的2行代码就可以了。这些东西在官方源码中都可以找到。我们要养成多看代码的习惯。对于提升自我很有帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值