当前位置:网站首页>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

1、 Single sign on solution :

2、JWT Tools :

3、 Realization JWP Integrate

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

  Add 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=0

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

 

原网站

版权声明
本文为[Fireworks youth·]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/209/202207280643302420.html