基于springboot+shiro阿里云短信服务实现短信验证登入

1、前期准备

登入阿里云,找到短信服务,开通短信功能记住一些重要的数据,这里不多说。

大概就是这个样子:
在这里插入图片描述

2、一些重要的参数密钥

在这里插入图片描述

3、代码部分

1、配置参数类

/*
  Created by IntelliJ IDEA.
  User: Kalvin
  Date: 2020/10/26
  Time: 19:52
*/
package com.music.system.config;


public class StaticPeram {
    
    
    /**
     * 手机验证部分配置
     */
    // 设置超时时间-可自行调整
    public final static String defaultConnectTimeout  = "sun.net.client.defaultConnectTimeout";
    public final static String defaultReadTimeout = "sun.net.client.defaultReadTimeout";
    public final static String Timeout = "10000";
    // 初始化ascClient需要的几个参数
    public final static String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
    public final static String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
    // 替换成你的AK (产品密)
    public final static String accessKeyId = "LTAI4G8UycM9iECpovbs6zrY";// 你的accessKeyId,填你自己的 上文配置所得  自行配置
    public final static String accessKeySecret = "6WC5fYmoVetc95Na08zVoDP5RuydzH";// 你的accessKeySecret,填你自己的 上文配置所得 自行配置
    // 必填:短信签名-可在短信控制台中找到
    public final static String SignName = "网欲音乐"; // 阿里云配置你自己的短信签名填入
    // 必填:短信模板-可在短信控制台中找到
    public final static String TemplateCode = "SMS_205122284"; // 阿里云配置你自己的短信模板填入

}

2、编写短信验证码生成工具,同时把验证码存到redis中设置过期时间
jedisClient.set(mobile+“code”,code,120);

/*
  Created by IntelliJ IDEA.
  User: Kalvin
  Date: 2020/10/26
  Time: 19:52
*/
package com.music.utils;


import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.music.system.config.StaticPeram;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

public class PhoneCode {
    
    

    /**
     * 阿里云短信服务配置
     * @param mobile
     * @return
     */
    public static CommonResponse getPhonemsg(String mobile,JedisClient jedisClient) {
    
    

        String code = vcode();
        jedisClient.set(mobile+"code",code,120);
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", StaticPeram.accessKeyId, StaticPeram.accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(StaticPeram.domain);
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", mobile);
        request.putQueryParameter("SignName", StaticPeram.SignName);
        request.putQueryParameter("TemplateCode", StaticPeram.TemplateCode);
        Map<String,Object> map = new HashMap<>();
        map.put("code",code);

        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(map));
        CommonResponse response = null;
        try {
    
    
             response = client.getCommonResponse(request);
            System.out.println(response.getData());

        } catch (ServerException e) {
    
    
            e.printStackTrace();

        } catch (ClientException e) {
    
    
            e.printStackTrace();

        }
        return response;
    }

    /**
     * 生成6位随机数验证码
     * @return
     */
    public static String vcode(){
    
    
        String vcode = "";
        for (int i = 0; i < 6; i++) {
    
    
            vcode = vcode + (int)(Math.random() * 9);
        }
        return vcode;
    }
}

3、短信验证登入realm

package com.music.system.shiro.realm;


import com.music.model.User;
import com.music.service.impl.UserService;
import com.music.utils.JedisClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;

/**
 * 手机验证码登录realm
 */
@Slf4j
public class UserPhoneRealm extends AuthorizingRealm {
    
    

    @Autowired
    private UserService userService;
    @Resource
    JedisClient jedisClient;

    @Override
    public String getName() {
    
    
        return LoginType.USER_PHONE.getType();
    }

    @Override
    public boolean supports(AuthenticationToken token) {
    
    
        if (token instanceof UserToken) {
    
    
            return ((UserToken) token).getLoginType() == LoginType.USER_PHONE;
        } else {
    
    
            return false;
        }
    }


    @Override
    public void setAuthorizationCacheName(String authorizationCacheName) {
    
    
        super.setAuthorizationCacheName(authorizationCacheName);
    }

    @Override
    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
    
    
        super.clearCachedAuthorizationInfo(principals);
    }

    /**
     * 认证信息.(身份验证) : Authentication 是用来验证用户身份
     *
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
    
    
        log.info("---------------- 手机验证码登录 ----------------------");
        UserToken token = (UserToken) authcToken;
        String phone = token.getUsername();
        // 手机验证码
        String validCode = String.valueOf(token.getPassword());
        System.out.println("validCode------>"+validCode);
        // 这里从redis中获取了验证码为 123456,并对比密码是否正确
        String redisCode = jedisClient.get(phone+"code");
        System.out.println("redisCode------>"+redisCode);
        //线上用redisCode取代123456
        if(!redisCode.equals(validCode)){
    
    
            log.debug("验证码错误,手机号为:{}", phone);
            throw new IncorrectCredentialsException();
        }

        User user = userService.findUserByPhone(phone);
        if(user == null){
    
    
            throw new UnknownAccountException();
        }
        // 用户为禁用状态
        if(!user.getShow()){
    
    
            throw new DisabledAccountException();
        }

        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user, //用户
                validCode, //密码
                getName()  //realm name
        );
        return authenticationInfo;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
    
        return null;
    }

}

/*
  Created by IntelliJ IDEA.
  User: Kalvin
  Date: 2020/10/26
  Time: 12:29
*/
package com.music.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.music.model.User;
import com.music.service.IUserService;
import com.music.service.impl.UserService;
import com.music.system.enums.ResultStatusCode;
import com.music.system.shiro.realm.LoginType;
import com.music.system.shiro.realm.UserToken;
import com.music.system.vo.Result;
import com.music.utils.JedisClient;
import com.music.utils.OptionalLog;
import com.music.utils.PhoneCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

import static com.music.system.shiro.realm.LoginType.USER_PASSWORD;
import static com.music.system.shiro.realm.LoginType.USER_PHONE;

@CrossOrigin
@RestController
@RequestMapping("admin")
public class LoginController {
    
    
    @Autowired
    private UserService userService;
    @Resource
    JedisClient jedisClient;
    /**
     * 用户密码登录
     */
    @RequestMapping("/login")
    public Result login(HttpServletRequest request){
    
    
        String loginName = request.getParameter("name");
        String password = request.getParameter("password");
        request.getSession().setAttribute("loginName",loginName);
        System.out.println("我是登录页的"+request.getSession().getAttribute("loginName"));
        System.out.println(loginName+"---->"+password);
        UserToken token = new UserToken(LoginType.USER_PASSWORD, loginName, password);
        return shiroLogin(token,LoginType.USER_PASSWORD);
    }



    /**
     * 用户点击获取验证码请求
     * */
    @RequestMapping("/sentCode")
    public Result sentCode(@RequestBody Map map){
    
    
        String phone = (String)map.get("phone");
        System.out.println("phone----->"+phone);
       // PhoneCode.getPhonemsg(phone,jedisClient);         //上线打开注释
        return new Result(1);
    }

    /**
     * 手机验证码登录
     */
    @RequestMapping("/loginByPhone")
    public Result loginByPhone(@RequestBody Map map){
    
    
        String phone = (String)map.get("phone");
        String code = (String)map.get("code");
        System.out.println(phone+"---->"+code);
        UserToken token = new UserToken(LoginType.USER_PHONE, phone, code);
        System.out.println("token---->"+token);
        return shiroLogin(token,LoginType.USER_PHONE);
    }
    


    @OptionalLog(modules="操作日志", methods="查询操作日志")
    @RequestMapping("/query")
    public void listLogInfo(){
    
    
        System.out.println("我进入来了。。。。");
    }

    public Result shiroLogin(UserToken token,LoginType loginType){
    
    
        User user = null;
        String userName = null;
        String phone = null;
        try {
    
    
            //登录不在该处处理,交由shiro处理
            Subject subject = SecurityUtils.getSubject();
            System.out.println("subject-------->"+subject);
            if(LoginType.USER_PASSWORD.equals(loginType)){
    
    
                userName = token.getUsername();
                user = userService.findUserByName(userName);
            }else if(LoginType.USER_PHONE.equals(loginType)){
    
    
                phone = token.getUsername();
                user = userService.findUserByPhone(phone);
            }

            System.out.println(phone+"================="+userName);
            //出现异常
            subject.login(token);

            if (subject.isAuthenticated()&&user!=null) {
    
    
                JSON json = new JSONObject();
                ((JSONObject) json).put("token", subject.getSession().getId());
                ((JSONObject) json).put("user",user);
                return new Result(ResultStatusCode.OK, json);
            }else{
    
    

                return new Result(ResultStatusCode.SHIRO_ERROR);
            }
        }catch (IncorrectCredentialsException | UnknownAccountException e){
    
    
            e.printStackTrace();
            return new Result(ResultStatusCode.NOT_EXIST_USER_OR_ERROR_PWD);
        }catch (LockedAccountException e){
    
    
            e.printStackTrace();
            return new Result(ResultStatusCode.USER_FROZEN);
        }catch (Exception e){
    
    
            e.printStackTrace();
            return new Result(ResultStatusCode.SYSTEM_ERR);
        }
    }
}

若对shiro不清楚可以先去了解一下在来看看效果会更好些。
这部分可以连接到上一篇文章https://blog.csdn.net/qq_43900677/article/details/112912929.
同时你可以关注微信公众号:幽灵邀请函 回复短信验证获取整个项目源代码,这里声明一下只是项目中的部分代码,和大家分享。

猜你喜欢

转载自blog.csdn.net/qq_43900677/article/details/113148413