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.
同时你可以关注微信公众号:幽灵邀请函 回复短信验证获取整个项目源代码,这里声明一下只是项目中的部分代码,和大家分享。