WTM (ASP.NET Core) custom identity authentication system configuration third-party external login (github login)

         I encountered a third-party login problem during the development of mobile applications using the WMT framework, so I added a third-party login to the WTM application myself. Here is an example of github. I refer to the blog SPA+.NET Core3.1 GitHub of the OvO God in the sky and   use AspNet.Security.OAuth.GitHub for third-party authorized login . Made a third-party login extension belonging to the WTM framework.

        1. Before GitHub authorized login, you must obtain client_id, client_secret how to obtain and test GitHub, please refer to GitHub Third Party Login this blog.

       Two, add configuration information in appsettings.json

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

        Third, add the user class WebUser inherited from FrameworkUserBase in the model layer of the WTM project, add OpenID field storage, and identity information such as openid returned by third-party login. And register in the database context of the DataAccess layer.

/// <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; }
    }

        Fourth, add the AuthenticationApi controller, and inject the configuration IConfiguration into the controller to obtain the configuration information of appsettings. And add the corresponding processing method

 public class AuthenticationApiController : BaseApiController
 {

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

        5. Add the ExternalLogin processing method to identify whether the external login request is initiated from the mobile phone or PCWEB, and carry the client_id to github to get the code value.

[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("参数错误");

        }

        6. Add the SignIn method, get the access_token from github, and return it to the callback page of SPA or PCWEB for processing.

[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]);
        }

        7. Add AutoLogin processing method, search in the openid field extended in WebUser according to the openid sent from the front-end callback page to the back-end, if not, return a null value, let the front-end page transfer to the login page for registration. If yes, issue JWT Token to SPA application, WTM MVC calls DoLogin generated by framework to login operation.

 

 [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/");
            }
        }

        The controller business logic is complete. Next, let's add login logic to WTM MVC and SPA applications.

        Eight, WTM MVC login

        1.1. Add a login button in the login view  

<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>

       

         Add login js method

 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 adds the LoginResult method to the login controller and returns the view as the callback page of 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/[email protected]"></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 end completes the setting. Next we continue to this SAP application side.

       Nine, SAP application side settings    

       1.1. Add the GitHubLogin method to the login.vue page and add it to the buttons and pictures you need @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. Add the login-result page, the address should correspond to the address in the appsettings.json file. The access_token returned in the background is received in onLoad, and the openid is requested in github to send to the background autoLogin and receive the 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>

       At this point, the github extension login is completed. It is worth mentioning that there are many good things in WTM that are not written in the documentation, such as the JWT token generation we use here.

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

       Only two simple lines of code are required. These things can be found in the official source code. We have to develop the habit of looking at the code more. Very helpful for self-improvement.

Guess you like

Origin blog.csdn.net/sxy_student/article/details/108034143