当前位置:网站首页>Day112. Shangyitong: Mobile verification code login function
Day112. Shangyitong: Mobile verification code login function
2022-07-28 08:38:00 【Fireworks youth·】
Catalog
One 、 Mobile phone verification code interface implementation
1、 stay service Create service_user modular
2、 Implement login and registration interface
One 、 Mobile verification code login generation token
Two 、 apply 、 Integrate Alibaba cloud SMS service , Build the interface
3、 ... and 、 Complete the login interface
Four 、 Front page implementation
One 、 Mobile phone verification code interface implementation
1、 stay service Create service_user modular
See courseware for details

2、 Implement login and registration interface
1. Analysis interface
* Parameters :LoginVo, request
* Return value :map( Sign in 、 user name )

2. controller
@Api(tags = " The user interface ")
@RestController
@RequestMapping("/api/user")
public class UserInfoApiController {
@Autowired
private UserInfoService userInfoService;
@ApiOperation(value = " Member login ")
@PostMapping("login")
public R login(@RequestBody LoginVo loginVo, HttpServletRequest request) {
loginVo.setIp(IpUtils.getIpAddr(request));
Map<String, Object> map = userInfoService.login(loginVo);
return R.ok().data(map);
}
}3. service
@Service
public class UserInfoServiceImpl extends
ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
// Member login
@Override
public Map<String, Object> login(LoginVo loginVo) {
//1. data verification
String phone = loginVo.getPhone();
String code = loginVo.getCode();
if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(code)){
throw new YyghException(20001," Incorrect registration information ");
}
//2. TODO Verification code
//3. Query user information according to mobile phone number
QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.eq("phone",phone);
UserInfo userInfo = baseMapper.selectOne(wrapper);
//4. User information is empty , Go to the registration function
if(userInfo==null){
userInfo = new UserInfo();
userInfo.setPhone(phone);
userInfo.setStatus(1); //0 lock 1 normal
baseMapper.insert(userInfo);
}
//5. Determine if the user is locked
if(userInfo.getStatus()==0){
throw new YyghException(20001," The user is locked ");
}
//6. Complete user information
// Return to the page display name
Map<String, Object> map = new HashMap<>();
String name = userInfo.getName();
if(StringUtils.isEmpty(name)) {
name = userInfo.getNickName();
}
if(StringUtils.isEmpty(name)) {
name = userInfo.getPhone();
}
//7. TODO The user login
map.put("token", "");
map.put("name", name);
return map;
}
}One 、 Mobile verification code login generation token
1、 Single sign on solution :
1.Session radio broadcast ( Broadcast storm 、 Waste bandwidth )
2.Redis+cookie
3. token+cookie
2、JWT Tools :
JWT(Json Web Token) Is a kind of implementation based on the JSON Open standards for .
JWT The declaration of is generally used to pass the authenticated user identity information between the identity provider and the service provider , To get resources from the resource server . For example, it's used in user login
JWT The most important function is to token The information of Anti-counterfeiting effect .
principle : One JWT from Three parts : Common part 、 Private sector 、 Signature part . Finally, the combination of the three base64 Code to get JWT.
3、 Realization JWP Integrate
1. common_utils Modules add dependencies
<!--JWP-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>2. add to JWT Tool class
public class JwtHelper {
private static long tokenExpiration = 24*60*60*1000;
private static String tokenSignKey = "123456";
public static String createToken(Long userId, String userName) {
String token = Jwts.builder()
.setSubject("YYGH-USER")
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.claim("userId", userId)
.claim("userName", userName)
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
.compressWith(CompressionCodecs.GZIP)
.compact();
return token;
}
public static Long getUserId(String token) {
if(StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Integer userId = (Integer)claims.get("userId");
return userId.longValue();
}
public static String getUserName(String token) {
if(StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws
= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String)claims.get("userName");
}
public static void main(String[] args) {
String token = JwtHelper.createToken(1L, "55");
System.out.println(token);
System.out.println(JwtHelper.getUserId(token));
System.out.println(JwtHelper.getUserName(token));
}
}3. perfect service Method , Realize the interface function 、
// Member login
@Override
public Map<String, Object> login(LoginVo loginVo) {
...
//7. TODO The user login
String token = JwtHelper.createToken(userInfo.getId(), userInfo.getName());
map.put("token", token);
map.put("name", name);
return map;Two 、 apply 、 Integrate Alibaba cloud SMS service , Build the interface
Official documents :Java SDK - SMS service - Alibaba cloud
1. Open Dingxin SMS service Dingxin ( Reference courseware )
Need to apply for signature 、 Templates


2. stay service Create sub modules under modules service_msm

Import dependence :
<dependencies>
<!-- Ali json Tools -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- Alibaba cloud core package -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
</dependencies>application.properties
# Service port
server.port=8204
# service name
spring.application.name=service-msm
spring.redis.host=192.168.86.86
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
# Maximum blocking waiting time ( A negative number means no limit )
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
# Minimum free time
# return json The global time format of
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
# nacos Service address
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848Add gateway configuration
# Set the routing id
spring.cloud.gateway.routes[3].id=service-msm
# To set up a route uri
spring.cloud.gateway.routes[3].uri=lb://service-msm
# Set route assertion , agent servicerId by auth-service Of /auth/ route
spring.cloud.gateway.routes[3].predicates= Path=/*/msm/**3. Realization controller
@Api(description = " Send verification code ")
@RestController
@RequestMapping("/api/msm")
public class MsmController {
@Autowired
private MsmService msmService;
@Autowired
private RedisTemplate<String,String> redisTemplate;
@ApiOperation(value = " Send verification code message ")
@GetMapping(value = "/send/{phone}")
public R send(@PathVariable String phone) {
//1. According to the mobile phone number redis, Get the verification code for verification
String redisCode = redisTemplate.opsForValue().get(phone);
if(redisCode!=null){
return R.ok();
}
//2. Get a new verification code , Package verification code
String code = RandomUtil.getFourBitRandom();
Map<String,String> paramMap = new HashMap<>();
paramMap.put("code",code);
//3. Call the interface to send SMS
boolean isSend = msmService.send(phone,paramMap);
//4. Store the verification code in Redis, Five minutes
if(isSend){
redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
return R.ok();
}else {
return R.error().message(" Failed to send SMS ");
}
}
}4. service
@Service
public class MsmServiceImpl implements MsmService {
// Send verification code message
@Override
public boolean send(String phone, Map<String, String> paramMap) {
//1. Check the cell phone number
if(StringUtils.isEmpty(phone)){
return false;
}
//3. Create a request object to store parameters AccessKey id、 Secret key
DefaultProfile profile =
DefaultProfile.getProfile("default", "LTAI5tMGtK....", "baAdNzxAjnIMKU3....");
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
//request.setProtocol(ProtocolType.HTTPS);
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
request.putQueryParameter("PhoneNumbers", phone);
// Be the same as the signature of the application
request.putQueryParameter("SignName", " My grain online education website ");
request.putQueryParameter("TemplateCode", "SMS_183195440");
request.putQueryParameter("TemplateParam", JSONObject.toJSONString(paramMap));
try {
//4. Send the request using the client object method , Get a response
CommonResponse response = client.getCommonResponse(request);
//5. Get the final result from the response
System.out.println(response.getData());
return response.getHttpResponse().isSuccess();
} catch (ClientException e) {
e.printStackTrace();
throw new YyghException(20001," SMS sending failed ");
}
}
}3、 ... and 、 Complete the login interface
1. Import redis To configure
#redis
spring.redis.host=192.168.86.86
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
# Maximum blocking waiting time ( A negative number means no limit )
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=02. modify service Method
@Autowired
RedisTemplate<String, String> redisTemplate;
// Member login
@Override
public Map<String, Object> login(LoginVo loginVo) {
//1. data verification
String phone = loginVo.getPhone();
String code = loginVo.getCode();
if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(code)){
throw new YyghException(20001," Incorrect registration information ");
}
//2. TODO Verification code
//2.1 From... According to the mobile phone number redis Take out the verification code
String rediscode = redisTemplate.opsForValue().get(phone);
//2.2 Comparison verification code
//2.2 Comparison verification code , Note the string null pointer
if(!code.equals(rediscode)){
throw new YyghException(20001," The verification code is wrong ");
}
//3. Query user information according to mobile phone number
QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.eq("phone",phone);
UserInfo userInfo = baseMapper.selectOne(wrapper);
//4. User information is empty , Go to the registration function
if(userInfo==null){
userInfo = new UserInfo();
userInfo.setPhone(phone);
userInfo.setStatus(1); //0 lock 1 normal
baseMapper.insert(userInfo);
}
//5. Determine if the user is locked
if(userInfo.getStatus()==0){
throw new YyghException(20001," The user is locked ");
}
//6. Complete user information
// Return to the page display name
Map<String, Object> map = new HashMap<>();
String name = userInfo.getName();
if(StringUtils.isEmpty(name)) {
name = userInfo.getNickName();
}
if(StringUtils.isEmpty(name)) {
name = userInfo.getPhone();
}
//7. TODO The user login
String token = JwtHelper.createToken(userInfo.getId(), userInfo.getName());
map.put("token", token);
map.put("name", name);
return map;
}Four 、 Front page implementation
1. establish API Interface method
userinfo.js
import request from '@/utils/request'
const api_name = `/api/user`
export default {
// validate logon
login(userInfo) {
return request({
url: `${api_name}/login`,
method: `post`,
data: userInfo
})
}
}msm.js
import request from '@/utils/request'
const api_name = `/api/msm`
export default {
// Send verification message
sendCode(mobile) {
return request({
url: `${api_name}/send/${mobile}`,
method: `get`
})
}
}2. modify layouts/myheader.vue
<template>
<div class="header-container">
<div class="wrapper">
<!-- logo -->
<div class="left-wrapper v-link selected">
<img style="width: 50px" width="50" height="50" src="~assets/images/logo.png">
<span class="text"> Shang Yitong Unified reservation and registration platform </span>
</div>
<!-- Search box -->
<div class="search-wrapper">
<div class="hospital-search animation-show">
<el-autocomplete class="search-input small" prefix-icon="el-icon-search" v-model="state"
:fetch-suggestions="querySearchAsync" placeholder=" Click to enter the name of the hospital " @select="handleSelect">
<span slot="suffix" class="search-btn v-link highlight clickable selected"> Search for </span>
</el-autocomplete>
</div>
</div>
<!-- On the right side -->
<!-- On the right side -->
<div class="right-wrapper">
<span class="v-link clickable"> Help center </span>
<span v-if="name == ''" class="v-link clickable" @click="showLogin()" id="loginDialog"> Sign in / register </span>
<el-dropdown v-if="name != ''" @command="loginMenu">
<span class="el-dropdown-link">
{
{ name }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu class="user-name-wrapper" slot="dropdown">
<el-dropdown-item command="/user"> Real name authentication </el-dropdown-item>
<el-dropdown-item command="/order"> Registered order </el-dropdown-item>
<el-dropdown-item command="/patient"> Patient management </el-dropdown-item>
<el-dropdown-item command="/logout" divided> Log out </el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
<!-- Login pop-up layer -->
<el-dialog :visible.sync="dialogUserFormVisible" style="text-align: left;" top="50px" :append-to-body="true"
width="960px" @close="closeDialog()">
<div class="container">
<!-- Mobile phone login #start -->
<div class="operate-view" v-if="dialogAtrr.showLoginType === 'phone'">
<div class="wrapper" style="width: 100%">
<div class="mobile-wrapper" style="position: static;width: 70%">
<span class="title">{
{ dialogAtrr.labelTips }}</span>
<el-form>
<el-form-item>
<el-input v-model="dialogAtrr.inputValue" :placeholder="dialogAtrr.placeholder"
:maxlength="dialogAtrr.maxlength" class="input v-input">
<span slot="suffix" class="sendText v-link" v-if="dialogAtrr.second > 0">{
{
dialogAtrr.second }}s </span>
<span slot="suffix" class="sendText v-link highlight clickable selected"
v-if="dialogAtrr.second == 0" @click="getCodeFun()"> To resend </span>
</el-input>
</el-form-item>
</el-form>
<!-- Send verification code or login dynamic -->
<div class="send-button v-button" @click="btnClick()"> {
{ dialogAtrr.loginBtn }}</div>
</div>
<div class="bottom">
<div class="wechat-wrapper" @click="weixinLogin()"><span class="iconfont icon"></span>
</div>
<span class="third-text"> Third party account login </span>
</div>
</div>
</div>
<!-- Mobile phone login #end -->
<!-- Wechat login #start -->
<div class="operate-view" v-if="dialogAtrr.showLoginType === 'weixin'">
<div class="wrapper wechat" style="height: 400px">
<div>
<div id="weixinLogin"></div>
</div>
<div class="bottom wechat" style="margin-top: -80px;">
<div class="phone-container">
<div class="phone-wrapper" @click="phoneLogin()"><span class="iconfont icon"></span>
</div>
<span class="third-text"> SMS verification code login </span>
</div>
</div>
</div>
</div>
<!-- Wechat login #end -->
<div class="info-wrapper">
<div class="code-wrapper">
<div><img src="//img.114yygh.com/static/web/code_login_wechat.png" class="code-img">
<div class="code-text"><span class="iconfont icon"></span> Wechat scanning and attention
</div>
<div class="code-text"> “ Quick appointment registration ”</div>
</div>
<div class="wechat-code-wrapper"><img src="//img.114yygh.com/static/web/code_app.png"
class="code-img">
<span class="iconfont icon"></span><div class="code-text"> Scan and download </div>
<div class="code-text"> “ Make an appointment for registration ”APP</div>
</div>
</div>
<div class="slogan">
<div>xxxxxx Officially designated platform </div>
<div> Fast registration Be safe </div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>3. JS Realization
<script>
import cookie from 'js-cookie'
import Vue from 'vue'
import userInfoApi from '@/api/userinfo'
import msmApi from '@/api/msm'
import hospitalApi from '@/api/hospital'
// Constant , Default initialization value
const defaultDialogAtrr = {
showLoginType: 'phone', // Control the switching between mobile login and wechat login
labelTips: ' Phone number ', // Input box prompt
inputValue: '', // Input box binding object
placeholder: ' Please input your mobile number ', // Input box placeholder
maxlength: 11, // Input box length control
loginBtn: ' Get verification code ', // Login button or get verification code button text
sending: true, // Whether the verification code can be sent
second: -1, // Countdown time second>0 : Show countdown second=0 : To resend second=-1 : Show nothing
clearSmsTime: null // Countdown timer task reference Close the login layer and clear the scheduled task
}
export default {
data() {
return {
userInfo: { // Login object
openid: "",
phone: "",
code: ""
},
dialogAtrr: defaultDialogAtrr, // Pop up layer objects
dialogUserFormVisible: false, // Whether the pop-up layer is displayed
name: "" // User name after login
}
},
created() {
// Determine if the user has logged in
this.showInfo()
},
methods: {
// Open the login registration pop-up layer
showLogin() {
this.dialogUserFormVisible = true
this.dialogAtrr = { ...defaultDialogAtrr } // Object storage operators , Open up new memory space
},
// Send verification code or login
btnClick() {
if (this.dialogAtrr.loginBtn == " Get verification code ") {
// Assign a value to the mobile number
this.userInfo.phone = this.dialogAtrr.inputValue
// Call the send verification code method
this.getCodeFun();
} else {
// Call the login method
this.login();
}
},
// Send verification code
getCodeFun() {
//1. Check cell phone number
if (!(/^1[34578]\d{9}$/.test(this.userInfo.phone))) {
this.$message.error(" The mobile number is incorrect ")
return;
}
//2. Change the pop-up layer object value to login
this.dialogAtrr.inputValue = ''
this.dialogAtrr.placeholder = ' Please enter the verification code '
this.dialogAtrr.maxlength = 6
this.dialogAtrr.loginBtn = ' Login immediately '
//3. Determine whether to send the verification code repeatedly sending
if (!this.dialogAtrr.sending) {
this.$message.error(" Please do not send repeatedly ")
return;
}
this.dialogAtrr.sending = false
//4. Send verification code
msmApi.sendCode(this.userInfo.phone)
.then(response => {
// Countdown method
this.timeDown();
})
.catch(e => {
//5. Send failed back before interface
this.$message.error(" Sending verification code failed ")
this.showLogin()
})
},
timeDown() {
if (this.clearSmsTime) {
clearInterval(this.clearSmsTime);
}
this.dialogAtrr.second = 60;
this.dialogAtrr.labelTips = ' The captcha has been sent to ' + this.userInfo.phone
this.clearSmsTime = setInterval(() => {
--this.dialogAtrr.second;
if (this.dialogAtrr.second < 1) {
// Clear timer , You need to be in pairs
clearInterval(this.clearSmsTime);
this.dialogAtrr.sending = true;
this.dialogAtrr.second = 0;
}
}, 1000);
},
// Login method
login() {
//1. Assign a value to the verification code
this.userInfo.code = this.dialogAtrr.inputValue
//2. Verify the validity of parameters
if (this.dialogAtrr.loginBtn == ' Submitting ...') {
this.$message.error(' Repeated submission ')
return;
}
if (this.userInfo.code == '') {
this.$message.error(' Verification code must be entered ')
return;
}
if (this.userInfo.code.length != 4) {
this.$message.error(' The format of the verification code is incorrect ')
return;
}
this.dialogAtrr.loginBtn = ' Submitting ...'
//3. Submit login information , Successfully set login status (name,cookie)
userInfoApi.login(this.userInfo)
.then(response => {
// Set login status
this.setCookies(response.data.name, response.data.token)
})
.catch(e => {
//4. Fail back
this.dialogAtrr.loginBtn = ' Log in right now '
})
},
// Set login status
setCookies(name, token) {
//domain: Scope of action
cookie.set("name", name, { domain: 'localhost' })
cookie.set("token", token, { domain: 'localhost' })
window.location.reload()
},
// Determine if you are logged in
showInfo() {
let token = cookie.get("token")
if (token) {
this.name = cookie.get("name")
console.log(this.name);
}
},
// Menu method Log out ?
loginMenu(command) {
if ('/logout' == command) {
cookie.set('name', '', { domain: 'localhost' })
cookie.set('token', '', { domain: 'localhost' })
// Jump to the page
window.location.href = '/'
} else {
window.location.href = command
}
},
handleSelect(item) {
window.location.href = '/hospital/' + item.hoscode
},
// Switch wechat login
weixinLogin() {
this.dialogAtrr.showLoginType = 'weixin'
},
// Switch mobile login
phoneLogin() {
this.dialogAtrr.showLoginType = 'phone'
this.showLogin()
}
}
};
</script>4. test 

边栏推荐
- classLoader加载的class的回收
- The fourth phase (2021-2022) research on the implementation of cloud native technology in traditional industries - central state-owned enterprises was officially released
- Sparksql and flinksql create and link table records
- Introduction to self drive tour of snow mountains in the West in January 2018
- Analysis and recurrence of network security vulnerabilities
- 【MindSpore易点通机器人-01】你也许见过很多知识问答机器人,但这个有点不一样
- Can‘t connect to server on ‘IP‘ (60)
- One key switch circuit
- QT 怎么删除布局里的所有控件?
- Unity切换到另一个场景的时候,发现该场景变暗了
猜你喜欢

49-OpenCv深入分析轮廓

Recruiting talents, gbase high-end talent recruitment in progress
![[Qt5] small software with 5 people randomly selected from the bid evaluation expert base](/img/ca/9f6bd6af45e2113c050edf3a65aaf2.png)
[Qt5] small software with 5 people randomly selected from the bid evaluation expert base

CarSim simulation quick start (XII) - Driver Model (2)

Unity切换到另一个场景的时候,发现该场景变暗了

What happens when you unplug the power? Gaussdb (for redis) dual life keeps you prepared

Hcip --- LDP and MPLS Technology (detailed explanation)
![[chart component kit] Shanghai daoning provides developers with steema download, trial and tutorial](/img/67/5373c45716ade5fbd1d3a980d8e5da.png)
[chart component kit] Shanghai daoning provides developers with steema download, trial and tutorial

The current value of uniapp's swiper dynamic setting does not take effect solution

MySQL how to add users and set permissions?
随机推荐
Sparksql and flinksql create and link table records
QT 怎么删除布局里的所有控件?
Usage of qmap
JS手写函数之slice函数(彻底弄懂包头不包尾)
Matlab (3) matlab program flow control statement
ASP. Net core foundation V
2022牛客多校第二场解题报告
Three different numbers with 0 in leetcode/ array
Use of namespaces
pyspark 写入数据到iceberg
[Qt5] small software with 5 people randomly selected from the bid evaluation expert base
MySQL怎么查询可以同时判断多个字段值是否存在
Pyspark changes the column order and saves it into iceberg database
ASP. Net core foundation IV
CAT1 4G+以太网开发板232数据通过4G模块TCP发到服务器
[reprint] man Rsync translation (Chinese Manual of Rsync command)
[mindspire YiDianTong robot-01] you may have seen many Knowledge Q & A robots, but this is a little different
pyspark更改列顺序存入iceberg数据库
49-OpenCv深入分析轮廓
中标捷报!南大通用GBase 8s中标南瑞集团2022年数据库框架项目