In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces "how to achieve fingerprint login on Web side". In daily operation, I believe that many people have doubts about how to achieve fingerprint login on Web side. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts of "how to achieve fingerprint login on Web side". Next, please follow the editor to study!
Preface
Now more and more laptops have built-in fingerprint identification, which is used to quickly enter the desktop from the lock screen, and some client software also supports fingerprint authentication.
A few days ago, I was thinking that since the client software can call the fingerprint device, the web side should also be able to call it. After a lot of trouble, I finally realized this function and applied it to my open source project.
In this article, I will share with you my implementation ideas and process. Developers who are interested are welcome to read this article.
Realization idea
The browser provides Web Authentication API, and we can use this set of API to call the user's fingerprint device to achieve user information authentication.
The video of the final implementation is as follows:
Implementation of fingerprint login on web
Registered fingerprint
First of all, we need to get the user credentials returned by the server, and then pass the user credentials to the fingerprint device, and then call up the fingerprint authentication of the system. After the authentication is passed, the callback function will return the device id and client information. We need to save these information on the server, which can be used to call the fingerprint device to verify the user's identity, so as to log in.
Next, let's summarize the process of registering fingerprints, as follows:
After the user successfully logs in to the website by other means, the server returns the user credential and saves the user credential locally
Detect whether there is a fingerprint device in the client
If it exists, pass the user credentials and user information returned by the server to the fingerprint registration function to create the fingerprint
Identity authentication is successful. The callback function returns the device id and client information, and saves the device id locally.
The device id and client information are sent to the server and stored in the specified user data.
Note: registration fingerprints can only work on websites that use https connections or localhost.
Fingerprint authentication
After authorized fingerprint login on our website, users will save their user credentials and device id locally. When users enter our website, they will get these two pieces of data locally, indicating whether it needs to log in to the system through fingerprints. After agreeing, they will send the device id and user credentials to the fingerprint device, and adjust the fingerprint authentication of the system. After passing the authentication, call the login API to obtain user information.
Next, we summarize the process of fingerprint authentication, as follows:
Obtain user credentials and device id locally
Detect whether there is a fingerprint device in the client
If it exists, pass the user credential and device id to the fingerprint authentication function for verification
Identity authentication is successful. Call login API to get user information.
Note: fingerprint authentication can only work on websites that use https connections or use localhost.
Realization process
In the previous chapter, we sorted out the specific implementation ideas of fingerprint login, and then let's look at the specific implementation process and code.
Server-side implementation
First of all, we need to write three interfaces on the server: get TouchID, register TouchID, and log in by fingerprint.
Get TouchID
This API is used to determine whether the logged-in user has registered a fingerprint on this site, and if so, return TouchID to the client to facilitate the user to log in next time.
The controller layer code is as follows
@ ApiOperation (value = "get TouchID", notes = "credentials required for fingerprint login through user id") @ CrossOrigin () @ RequestMapping (value = "/ getTouchID", method = RequestMethod.POST) public ResultVO getTouchID (@ ApiParam (name = "incoming userId", required = true) @ Valid @ RequestBody GetTouchIdDto touchIdDto, @ RequestHeader (value = "token") String token) {JSONObject result = userService.getTouchID (JwtUtil.getUserId (token)) If (result.getEnum (ResultEnum.class, "code"). GetCode () = 0) {/ / touchId obtained return ResultVOUtil.success successfully (result.getString ("touchId"));} / / returned error message return ResultVOUtil.error (result.getEnum (ResultEnum.class, "code") .getCode (), result.getEnum (ResultEnum.class, "code") .getMessage ()) }
The specific implementation code of the interface is as follows
/ / get TouchID @ Override public JSONObject getTouchID (String userId) {JSONObject returnResult = new JSONObject (); / / query from the database based on the current user id touchId User user = userMapper.getTouchId (userId); String touchId = user.getTouchId (); if (touchId! = null) {/ / touchId exists returnResult.put ("code", ResultEnum.GET_TOUCHID_SUCCESS) ReturnResult.put ("touchId", touchId); return returnResult;} / / touchId does not exist returnResult.put ("code", ResultEnum.GET_TOUCHID_ERR); return returnResult;}
Register for TouchID
This interface is used to receive the TouchID and client information returned by the client fingerprint device, and save the obtained information to the specified user of the database.
The controller layer code is as follows
@ ApiOperation (value = "register TouchID", notes = "save touchid and other information returned by the client") @ CrossOrigin () @ RequestMapping (value = "/ registeredTouchID", method = RequestMethod.POST) public ResultVO registeredTouchID (@ ApiParam (name = "incoming userId", required = true) @ Valid @ RequestBody SetTouchIdDto touchIdDto, @ RequestHeader (value = "token") String token) {JSONObject result = userService.registeredTouchID (touchIdDto.getTouchId (), touchIdDto.getClientDataJson (), JwtUtil.getUserId (token)) If (result.getEnum (ResultEnum.class, "code"). GetCode () = 0) {/ / touchId obtained return ResultVOUtil.success successfully (result.getString ("data"));} / / returned error message return ResultVOUtil.error (result.getEnum (ResultEnum.class, "code") .getCode (), result.getEnum (ResultEnum.class, "code") .getMessage ()) }
The specific implementation code of the interface is as follows
/ register TouchID @ Override public JSONObject registeredTouchID (String touchId, String clientDataJson, String userId) {JSONObject result = new JSONObject (); User row = new User (); row.setTouchId (touchId); row.setClientDataJson (clientDataJson); row.setUserId (userId); / / update touchId and client information int updateResult = userMapper.updateTouchId (row) according to userId If (updateResult > 0) {result.put ("code", ResultEnum.SET_TOUCHED_SUCCESS); result.put ("data", "touch_id set successfully"); return result;} result.put ("code", ResultEnum.SET_TOUCHED_ERR); return result;}
Fingerprint login
This interface receives the user credentials and touchId sent by the client, then verifies them with the data in the database and returns the user information.
The controller layer code is as follows
@ ApiOperation (value = "fingerprint login", notes = "login to the system through touchId and user credentials") @ CrossOrigin () @ RequestMapping (value = "/ touchIdLogin", method = RequestMethod.POST) public ResultVO touchIdLogin (@ ApiParam (name = "incoming TouchID and user credentials", required = true) @ Valid @ RequestBody TouchIDLoginDto touchIDLogin) {JSONObject result = userService.touchIdLogin (touchIDLogin.getTouchId (), touchIDLogin.getCertificate ()); return LoginUtil.getLoginResult (result);}
The specific implementation code of the interface is as follows
/ / fingerprint login @ Override public JSONObject touchIdLogin (String touchId, String certificate) {JSONObject returnResult = new JSONObject (); User row = new User (); row.setTouchId (touchId); row.setUuid (certificate); User user = userMapper.selectUserForTouchId (row); String userName = user.getUserName (); String userId = user.getUserId () / / if the user name is null, the error message if (userName = = null) {/ / fingerprint authentication failed returnResult.put ("code", ResultEnum.TOUCHID_LOGIN_ERR); return returnResult;} / / fingerprint authentication is successful, return the user information to the client /. The code is omitted here, and you can return user information according to your needs. / / returnResult.put ("code", ResultEnum.LOGIN_SUCCESS); return returnResult;}
Front-end implementation
In the front part, we need to combine the existing login logic with fingerprint authentication, and we need to implement two functions: fingerprint registration and fingerprint login.
Fingerprint registration
For this function, we need to receive three parameters: user name, user id and user credential. We need these three parameters to call the fingerprint device to generate fingerprints. The specific implementation code is as follows:
TouchIDRegistered: async function (userName: string, userId: string, certificate: string) {/ / verify whether the device supports touchID const hasTouchID = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable (); if (hasTouchID & & window.confirm ("detect that your device supports fingerprint login, is it enabled?") ) {/ / Update registration credentials this.touchIDOptions.publicKey.challenge = this.base64ToArrayBuffer (certificate); / / update user name, user id this.touchIDOptions.publicKey.user.name = userName; this.touchIDOptions.publicKey.user.displayName = userName; this.touchIDOptions.publicKey.user.id = this.base64ToArrayBuffer (userId) / / call fingerprint device to create fingerprint const publicKeyCredential = await navigator.credentials.create (this.touchIDOptions); if (publicKeyCredential & & "rawId" in publicKeyCredential) {/ / convert rowId to base64 const rawId = publicKeyCredential ["rawId"]; const touchId = this.arrayBufferToBase64 (rawId); const response = publicKeyCredential ["response"] / / get client information const clientDataJSON = this.arrayBufferToString (response ["clientDataJSON"]) / / call the registration TouchID interface this.$api.touchIdLogingAPI .registeredTouchID ({touchId: touchId) ClientDataJson: clientDataJSON}) .then ((res: responseDataType) = > {if (res.code = 0) {/ / Save touchId for fingerprint login localStorage.setItem ("touchId", touchId) Return;} alert (res.msg););}
In the above function, when creating a fingerprint, an object is used, which must be passed to create a fingerprint. Its definition and interpretation of each parameter are as follows:
Const touchIDOptions = {publicKey: {name: "chat-system"}, / / website information user: {name: ", / / user name id:", / / user id (ArrayBuffer) displayName: "/ / user name}, pubKeyCredParams: [{type:" public-key " Alg:-7 / / accepted algorithm}], challenge: ", / / credential (touchIDOptions) authenticatorSelection: {authenticatorAttachment:" platform "}
Because some parameters in touchIDOptions require ArrayBuffer type, and the data stored in our database is in base64 format, we need to implement the conversion function between base64 and ArrayBuffer. The implementation code is as follows:
Base64ToArrayBuffer: function (base64: string) {const binaryString = window.atob (base64); const len = binaryString.length; const bytes = new Uint8Array (len); for (let I = 0; I
< len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; }, arrayBufferToBase64: function(buffer: ArrayBuffer) { let binary = ""; const bytes = new Uint8Array(buffer); const len = bytes.byteLength; for (let i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return window.btoa(binary); } 指纹认证通过后,会在回调函数中返回客户端信息,数据类型是ArrayBuffer,数据库需要的格式是string类型,因此我们需要实现ArrayBuffer转string的函数,实现代码如下: arrayBufferToString: function(buffer: ArrayBuffer) { let binary = ""; const bytes = new Uint8Array(buffer); const len = bytes.byteLength; for (let i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return binary; } 注意:用户凭证中不能包含 _ 和 **-**这两个字符,否则base64ToArrayBuffer函数将无法成功转换。 指纹登录 这个函数接收2个参数:用户凭证、设备id,我们会通过这两个参数来调起客户端的指纹设备来验证身份,具体的实现代码如下: touchIDLogin: async function(certificate: string, touchId: string) { // 校验设备是否支持touchID const hasTouchID = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(); if (hasTouchID) { // 更新登录凭证 this.touchIDLoginOptions.publicKey.challenge = this.base64ToArrayBuffer( certificate ); // 更新touchID this.touchIDLoginOptions.publicKey.allowCredentials[0].id = this.base64ToArrayBuffer( touchId ); // 开始校验指纹 await navigator.credentials.get(this.touchIDLoginOptions); // 调用指纹登录接口 this.$api.touchIdLogingAPI .touchIdLogin({ touchId: touchId, certificate: certificate }) .then((res: responseDataType) =>{if (res.code = = 0) {/ / stores current user information localStorage.setItem ("token", res.data.token); localStorage.setItem ("refreshToken", res.data.refreshToken); localStorage.setItem ("profilePicture", res.data.avatarSrc); localStorage.setItem ("userID", res.data.userID) LocalStorage.setItem ("username", res.data.username); const certificate = res.data.certificate; localStorage.setItem ("certificate", certificate); / / Jump message component this.$router.push ({name: "message"}); return } / / switch back to the login interface this.isLoginStatus = loginStatusEnum.NOT_LOGGED_IN; alert (res.msg);});}}
Note: after registering a new fingerprint, the old Touch id will become invalid and can only be logged in through the new Touch ID, otherwise the system will not be able to adjust the fingerprint device and will report an error: there is something wrong with the authentication.
Integrate existing login logic
After completing the above steps, we have implemented the registration and login logic of the entire fingerprint, so let's take a look at how to integrate it with the existing login.
Call fingerprint registration
When a user successfully logs in with a user name, password or third-party platform authorization, we call the fingerprint registration function to prompt the user whether to authorize this website. The implementation code is as follows:
AuthLogin: function (state: string, code: string, platform: string) {this.$api.authLoginAPI. AuthorizeLogin ({state: state, code: code, platform: platform}) .then (async (res: responseDataType) = > {if (res.code = = 0) {/ /. If the authorization login is successful, other codes omit. / save user credentials for fingerprint login const certificate = res.data.certificate; localStorage.setItem ("certificate", certificate); / / verify whether the device supports touchID const hasTouchID = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable (); if (hasTouchID) {/ /. Other codes are omitted. / get Touch ID Check whether the user has authorized the fingerprint login of this website to this.$api.touchIdLogingAPI .getTouchID ({userId: userId}) .then (async (res: responseDataType) = > {if (res.code! = = 0) {/ / touchId does not exist Ask the user whether to register for touchId await this.touchIDRegistered (username, userId, certificate) } / / Save touchid localStorage.setItem ("touchId", res.data); / / Jump message component await this.$router.push ({name: "message"});}); return } / / device does not support touchID, directly jump to message component await this.$router.push ({name: "message"}); return;} / / login failed, switch back to login interface this.isLoginStatus = loginStatusEnum.NOT_LOGGED_IN; alert (res.msg) });}
The final effect is as follows:
Each time a third-party platform authorizes the login, it will detect whether the current user has authorized this website, and if so, save the Touch ID locally for direct login by fingerprint.
Call fingerprint login
After loading the login page for 1 second, we extract the user's credentials and Touch ID locally from the user. If there is, we will prompt the user whether to log in to the system through fingerprint. The specific code is as follows:
Mounted () {const touchId = localStorage.getItem ("touchId"); const certificate = localStorage.getItem ("certificate"); / / if touchId exists, call fingerprint login if (touchId & & certificate) {/ / prompt the user whether touchId login is required (() = > {if (window.confirm ("you have authorized this website to log in through fingerprint, do you want to log in now?")) {this.touchIDLogin (certificate, touchId);}}, 1000);}}
The final effect is as follows:
Project address
For the full address of this article code, please move to: Login.vue
Online experience address: chat-system
Project GitHub address: chat-system-github
At this point, the study on "how to achieve fingerprint login on the Web side" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
The use of lcx and htran attachment: http://down.51cto.com/data/2363780
© 2024 shulou.com SLNews company. All rights reserved.