DDD實戰進階第一波(十):開發一般業務的大健康行業直銷系統(實現經銷商登錄倉儲與邏輯)


上一篇文章主要講了經銷商注冊的倉儲和領域邏輯的實現,我們先把應用服務協調完成經銷商注冊這部分暫停一下,后面文章統一講。

這篇文章主要講講經銷商登錄的倉儲和相關邏輯的實現。

在現代應用程序前后端分離的實現中,通常不是將用戶登錄的信息存儲在服務器端Session,因為會存在服務器Session無法傳遞的情況,也存在WebApi調用時

無法通過Authorize Attribute判斷用戶是否已經登錄並獲取用戶身份信息的問題。所以現代應用程序都是由服務器后端返回Token給客戶端,客戶端將Token存儲在客戶端

Session中,客戶端在請求后端接口時,帶上Token,服務器端就能夠識別客戶端是否經過身份驗證,而且可以直接拿到客戶端的身份。

要實現經銷商的登錄,主要由以下幾個步驟組成。

1.實現經銷商登錄時信息查詢的倉儲。

2.在應用服務中,單獨建立一個查詢文件夾放置經銷商登錄的查詢邏輯。

3.在登錄WebApi中,調用應用服務的查詢邏輯並分發Token。

 

1.實現經銷商登錄時信息查詢的倉儲:

 public interface ILoginRepository
    {
            Guid UserLogin(string tel, string password);
    }
 public class LoginEFCoreRepository : ILoginRepository
    {
        private readonly DbContext context;
        public LoginEFCoreRepository(DbContext context)
        {
            this.context = context;
        }
        public Guid UserLogin(string tel, string password)
        {
            var dealercontext = this.context as DealerEFCoreContext;
            var enpassword = MD5Encrption.GetMd5Str(password);
            var logindealer=
                dealercontext.Login.Where(p => p.Code == tel && p.Password == enpassword).FirstOrDefault();
            if (logindealer != null)
            {
                return logindealer.DealerId;
            }
            return Guid.Empty;
        }

          }

2.應用服務中調用倉儲完成用戶登錄的查詢

public class UserLoginQuery:BaseAppSrv
    {
        private readonly IRepository irepository;
        private readonly ILoginRepository iloginrepository;
        public UserLoginQuery(IRepository irepository, ILoginRepository iloginrepository)
        {
            this.iloginrepository = iloginrepository;
            this.irepository = irepository;
        }
        public Guid Login(UserLoginDTO userlogindto)
        {
            try
            {
                using (irepository)
                {
                    return iloginrepository.UserLogin(userlogindto.Telphone, userlogindto.Password);
                }
            }
            catch(Exception error)
            {
                throw error;
            }
        }
    }

3.在登錄WebApi中調用應用服務,並分發令牌

[AllowAnonymous]
        [HttpPost]
        [Route("UserLogin")]
        public ResultEntity<UserLoginResultDTO> UserLogin([FromBody] UserLoginDTO userlogindto)
        {
            var result = new ResultEntity<UserLoginResultDTO>();
            var idealercontext = servicelocator.GetService<IDealerContext>();
            var irepository =
                servicelocator.GetService<IRepository>(new ParameterOverrides { { "context", idealercontext } });
            var iloginrepository = servicelocator.GetService<ILoginRepository>(new ParameterOverrides { { "context", idealercontext } });
            UserLoginQuery userloginquery = new UserLoginQuery(irepository, iloginrepository);
            try
            {
                var dealerid = userloginquery.Login(userlogindto);
                if (dealerid != Guid.Empty)
                {
                    var token = new JwtTokenBuilder()
                        .AddSecurityKey(JwtSecurityKey.Create("msshcjsecretmsshcjsecret"))
                        .AddSubject(userlogindto.Telphone)
                        .AddIssuer("DDD1ZXSystem")
                        .AddAudience("DDD1ZXSystem")
                        .AddClaim("role", "NormalUser")                        
                        .AddExpiry(600)
                        .Build();

                    var userloginresultdto = new UserLoginResultDTO();
                    userloginresultdto.Tel = userlogindto.Telphone;
                    userloginresultdto.DealerId = dealerid;
                    userloginresultdto.Token = token.Value;

                    result.IsSuccess = true;
                    result.Data = userloginresultdto;
                    result.Msg = "登錄成功!";
                }
                else
                {
                    result.ErrorCode = 300;
                    result.Msg = "登錄失敗!";
                }

            }
            catch (Exception error)
            {
                result.ErrorCode = 200;
                result.Msg = error.Message;
            }
            return result;
        }

 這里的UserLoginDTO定義如下:

  public class UserLoginDTO
    {
        public string Telphone { get; set; }
        public string Password { get; set; }
    }

這里的UserLoginResultDTO定義如下:

 public class UserLoginResultDTO
    {
        public string Tel { get; set; }
        public Guid DealerId { get; set; }
        public string Token { get; set; }
    }

這里的JwtTokenBuilder定義如下:

public class JwtTokenBuilder
    {
        private SecurityKey securityKey = null;
        private string subject = "";
        private string issuer = "";
        private string audience = "";
        private Dictionary<string, string> claims = new Dictionary<string, string>();
        private int expiryInMinutes = 5;

        public JwtTokenBuilder AddSecurityKey(SecurityKey securityKey)
        {
            this.securityKey = securityKey;
            return this;
        }
        public JwtTokenBuilder AddSubject(string subject)
        {
            this.subject = subject;
            return this;
        }
        public JwtTokenBuilder AddIssuer(string issuer)
        {
            this.issuer = issuer;
            return this;
        }
        public JwtTokenBuilder AddAudience(string audience)
        {
            this.audience = audience;
            return this;
        }
        public JwtTokenBuilder AddClaim(string type,string value)
        {
            this.claims.Add(type, value);
            return this;
        }
        public JwtTokenBuilder AddExpiry(int expiryInMinutes)
        {
            this.expiryInMinutes = expiryInMinutes;
            return this;
        }

        public JwtToken Build()
        {
            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Sub,this.subject),
                new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())

            }.Union(this.claims.Select(item => new Claim(item.Key, item.Value)));

            var token = new JwtSecurityToken(issuer: this.issuer, audience: this.audience, claims: claims,
                expires: DateTime.UtcNow.AddMinutes(this.expiryInMinutes), signingCredentials:
                new SigningCredentials(this.securityKey, SecurityAlgorithms.HmacSha256));
            return new JwtToken(token);
        }
    }

這里的BearerUserInfo定義如下:

public class BearerUserInfo:Controller
    {
        public string GetUserName()
        {
            var principal = HttpContext.User as ClaimsPrincipal;
            if (principal != null)
            {
                foreach(var claim in principal.Claims)
                {
                    if (claim.Subject != null)
                    {
                        var subjectclaims = claim.Subject.Claims as List<Claim>;
                        return subjectclaims[0].Value;
                    }
                }
            }
            return null;
        }
    }

這里的JwtSecurityKey定義如下:

public static class JwtSecurityKey
    {
        public static SymmetricSecurityKey Create(string secret)
        {
            return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
        }
    }

這里的JwtToken定義如下:

public class JwtToken
    {
        private JwtSecurityToken token;
        public JwtToken(JwtSecurityToken token)
        {
            this.token = token;
        }
        public DateTime ValidTo => token.ValidTo;
        public string Value => new JwtSecurityTokenHandler().WriteToken(this.token);
    }

 

以上采用了.net core中關於OWIN的使用,具體不清楚的屬性和方法,可以參考OWIN中.net core的實現標准,這里就不累述了,具體可以參考微信公眾號中的視頻講解。

QQ討論群:309287205

DDD實戰進階視頻請關注微信公眾號:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM