Is the Microsoft. AspNet. Identity. EntityFramework introduced for Identity authentication still causing multiple contexts. Is it difficult to rename the generated DB ?, Aspnet. identity
The most recent project needs to integrate authentication in the API, So Microsoft is selected. aspNet. identity. core, and Microsoft. aspNet. identity. but in the implementation process, we find that Microsoft. aspNet. identity. entityFramework causes multiple EF contexts in the Code. Although there are renaming Methods everywhere on the internet, multiple contexts in one project are always unacceptable for patients with obsessive-compulsive disorder. Check whether there are any solutions.
After obtaining the source code, it is found that Microsoft. AspNet. Identity. EntityFramework only encapsulates EF and can be done by yourself. The following describes the implementation ideas.
This article is based on web api5.2 + unity + ef
1. inheritance systems that can be viewed through source code
We can see that the Core is the UserManager in the Core, and Microsoft. AspNet. Identity. EntityFramework encapsulates the EF context and operation model.
2. Customize the model as needed
Microsoft. AspNet. Identity. EntityFramework IdentityRole-> RoleInfo: IRole only needs to inherit IRole. By default, left join is optional
IdentityUser-> UserInfo: IUser
Custom UserRoleInfo, UserClaimInfo, AccountLoginInfo
3. Add the new model to your EF Context
You can use codefirst to customize the table name and segment type in Map.
4. Replace the UserStore and RoleStore in Microsoft. AspNet. Identity. EntityFramework with the Store for the Identity operation.
Define a new interface to facilitate Injection
/// <Summary> /// ID verification Store interface /// </summary> public interface ICustomerIdentityStore: IUserLoginStore <UserInfo, string>, IUserClaimStore <UserInfo, string>, IUserRoleStore <UserInfo, string>, IUserPasswordStore <UserInfo, string>, Region <UserInfo, string>, IQueryableUserStore <UserInfo, string>, IUserEmailStore <UserInfo, string>, IUserPhoneNumberStore <UserInfo, string>, IUserTwoFactorStore <UserInfo, string>, IUserLockoutStore <UserInfo, string>, IUserStore <UserInfo> {}
Then implement its interface, and inject the context warehouse into the implementation to operate the DB.
5. Custom Identity Authentication warehousing interface and implementation (sample code)
/// <Summary> /// Identity Authentication warehouse /// </summary> public interface IAuthRepository {/// <summary> /// register a user /// </summary> /// <param name = "userModel"> </param> /// <returns> </returns> Task <IdentityResult> RegisterUser (UserModel userModel ); /// <summary> /// find the user /// </summary> /// <param name = "userName"> </param> /// <param name = "password"> </param> // <returns> </returns> Task <UserInfo> FindUser (string userName, string password ); /// <summary> /// query AppClient information /// </summary> /// <param name = "clientId"> </param> /// <returns> </returns> AppClientInfo FindClient (string clientId ); /// <summary> /// add Token information /// </summary> /// <param name = "token"> </param> /// <returns> </returns> Task <bool> AddRefreshToken (RefreshTokenInfo token ); /// <summary> /// remove the token information /// </summary> /// <param name = "refreshTokenId"> </param> /// <returns> </returns> Task <bool> RemoveRefreshToken (string refreshTokenId ); /// <summary> /// remove the token information /// </summary> /// <param name = "refreshToken"> </param> /// <returns> </returns> Task <bool> RemoveRefreshToken (RefreshTokenInfo refreshToken ); /// <summary> /// search for the token information /// </summary> /// <param name = "refreshTokenId"> </param> /// <returns> </returns> Task <RefreshTokenInfo> FindRefreshToken (string refreshTokenId ); /// <summary> /// search for all refresh token information /// </summary> /// <returns> </returns> List <RefreshTokenInfo> GetAllRefreshTokens (); /// <summary> /// query user information through logon information /// </summary> /// <param name = "loginInfo"> </param> /// <returns> </returns> Task <UserInfo> FindAsync (UserLoginInfo loginInfo ); /// <summary> /// create user information /// </summary> /// <param name = "user"> </param> /// <returns> </returns> Task <IdentityResult> CreateAsync (UserInfo user ); /// <summary> /// Add User Logon Information /// </summary> /// <param name = "userId"> </param> /// <param name = "login"> </param> // <returns> </returns> Task <IdentityResult> AddLoginAsync (string userId, userLoginInfo login );}
Then add its implementation
/// <Summary> /// Identity Authentication warehouse /// </summary> public class AuthRepository: IAuthRepository {// <summary> // warehouse interface // </summary> private readonly IUnitRepository _ repository; /// <summary> /// work unit /// </summary> private readonly IUnitOfWork _ unitOfWork; /// <summary> /// user management /// </summary> private readonly UserManager <UserInfo> _ userManager; /// <summary> /// ctor /// </summary> /// <param name = "rep Ository "> </param> // <param name =" unitOfWork "> </param> // <param name =" userStore "> </param> public AuthRepository (IUnitRepository repository, IUnitOfWork unitOfWork, ITaurusIdentityStore userStore) {_ repository = repository; _ unitOfWork = unitOfWork; _ userManager = new UserManager <UserInfo> (userStore );} public async Task <IdentityResult> AddLoginAsync (string userId, UserLoginInfo login) {var re Sult = await _ userManager. addLoginAsync (userId, login); return result;} public async Task <bool> AddRefreshToken (RefreshTokenInfo token) {var existingToken = _ repository. firstOrDefault <RefreshTokenInfo> (r => r. subject = token. subject & r. appClientId = token. appClientId); if (existingToken! = Null) {var result = await RemoveRefreshToken (existingToken);} _ repository. insert (token); return _ unitOfWork. saveChanges ()> 0;} public async Task <IdentityResult> CreateAsync (UserInfo user) {var result = await _ userManager. createAsync (user); return result;} public async Task <UserInfo> FindAsync (UserLoginInfo loginInfo) {var user = await _ userManager. findAsync (loginInfo); return user;} publi C AppClientInfo FindClient (string clientId) {var client = _ repository. firstOrDefault <AppClientInfo> (s => s. id = clientId); return client;} public Task <RefreshTokenInfo> FindRefreshToken (string refreshTokenId) {var refreshToken = _ repository. firstOrDefault <RefreshTokenInfo> (s => s. tokenId = refreshTokenId); return Task. fromResult (refreshToken);} public async Task <UserInfo> FindUser (string use RName, string password) {var user = await _ userManager. findAsync (userName, password); return user;} public List <RefreshTokenInfo> GetAllRefreshTokens () {return _ repository. all <RefreshTokenInfo> (). toList ();} public async Task <IdentityResult> RegisterUser (UserModel userModel) {var user = new UserInfo {UserName = userModel. userName, Id = Guid. newGuid (). toString (), FullName = "test", CreateTime = DateTime. now, CreateBy = Guid. empty. toString (), UpdateBy = Guid. empty. toString (), UpdateTime = DateTime. now}; var result = await _ userManager. createAsync (user, userModel. password); return result;} public Task <bool> RemoveRefreshToken (RefreshTokenInfo refreshToken) {_ repository. deleteItem (refreshToken); var result = _ unitOfWork. saveChanges ()> 0; return Task. fromResult (result);} public Task <B Ool> upload (string refreshTokenId) {var refreshToken = _ repository. FirstOrDefault <RefreshTokenInfo> (s => s. Id = refreshTokenId); var result = false; if (refreshToken! = Null) {_ repository. DeleteItem (refreshToken); result = _ unitOfWork. SaveChanges ()> 0;} return Task. FromResult (result );}}
The idea is to construct a UserManager instance by injecting ICustomerIdentityStore (IUserStore)
6. Use the IAuthRepository interface directly.
In this way, all operations are controlled in their own code. You no longer need to modify the table name, REMAP fields, and maintain multiple contexts.
If you have any questions, please discuss them.
Thank you.