单点登录及JWT
单点登录概念实现方式JWT aly短信服务
建立相关模块并配置实现功能
单点登录及JWT部分内容引用https://achang.blog.csdn.net/article/details/114419056
单点登录概念单点登录(single sign on),简称SSO
应用于集群分布中,假设有多个服务器或多个tomcat,用户在一个服务器中登录,则其他的服务器就不需要登录(好比登录了QQ农场就不用登录QQ牧场)
另外,如果是单一服务器的化,直接用session实现登录更为方便,如
实现方式session.setAttribute(“user”,user)
session.getAttribute()
1、session广播机制
即session的复制,但浪费资源,用比较少
过期时间设置:session默认过期时间30min,可修改这个来决定过期时间
2、cookie + redis实现
(1)在项目任意一个模块登录,然后将数据放到cookie和redis中
在redis中,key中存入随机唯一值(用户id、uid等),value中存放用户数据
(2)把redis中生成的key值放到cookie中
(3)访问项目其他模块,发送请求带着cookie,从cookie中的值拿到redis做查询,如果能查询出数据,则已经登录,否则没有登录
过期时间设置:可以设置redis中的过期时间
3、使用token实现
token(令牌):按照一定规则(加密)生成的字符串,字符串可以包含用户信息
(1)在项目某模块登录,然后按照规则生成字符串,把登录之后用户包含到生成字符串里面,把字符串返回(可以
通过cookie返回,或通过地址栏返回)
(2)再去访问项目其他模块,每次访问在地址栏带着生成字符串,在访问模块里面获取地址栏字符串,根据字符串获取用户信息,如果可以获取就是已登录
token是按照一定规则生成的字符串,JWT是规定好的规则,使用JWT可以生成字符串
组成如下:
java中实现
依赖pom.xml
io.jsonwebtoken jjwt
JwtUtils.java(能看懂即可)
package com.liang.commonutils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
public class JwtUtils {
//token过期时间
public static final long EXPIRE = 1000 * 60 * 60 * 24;
//秘钥,每个公司生成规则不一样
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";
//生成token字符串方法
public static String getJwtToken(String id, String nickname) {
String JwtToken = Jwts.builder()
//设置jwt头信息,红色部分,内容固定,不需要改
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.setSubject("guli-user")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))//设置过期时间
//设置token主体部分,存储用户信息,可设置多个值
.claim("id", id)
.claim("nickname", nickname)
//设置签名哈希(防伪标志)
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
return JwtToken;
}
public static boolean checkToken(String jwtToken) {
if (StringUtils.isEmpty(jwtToken)) return false;
try {
//根据设置的防伪码解析token
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = request.getHeader("token");
if (StringUtils.isEmpty(jwtToken)) return false;
//根据设置的防伪码解析token
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = request.getHeader("token");
if (StringUtils.isEmpty(jwtToken)) return "";
//根据设置的防伪码解析token,获取对象
Jws claimsJws =
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
//获取token有效载荷【用户信息】
Claims claims = claimsJws.getBody();
return (String) claims.get("id");
}
}
aly短信服务
建立相关模块并配置
创建模块service-msm,创建相关controller及service等文件夹
配置application.properties文件,将数据库信息、redis信息等配置好
# 用于aly短信服务
# 服务器端口
server.port=8005
# 服务名
spring.application.name=service-msm
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
# nacos注册中心
spring.cloud.nacos.discovery.server-addr= localhost:8848
#配置mapper xml文件的路径
#mybatis-plus.mapper-locations=classpath:com/liang/msmservice/mapper/xml
public static ArrayList getRandom(List list, int n) {
Random random = new Random();
HashMap
然后根据aly的示例代码进行修改,这里需要导入相关依赖
com.aliyun
aliyun-java-sdk-dysmsapi
2.2.1
controller.java
@Autowired
public MsmService msmService;
//发送短信方法
@GetMapping("sent/{phone}")
public R sendMsm(@PathVariable String phone){
//验证码的值是程序设计的
String code = RandomUtil.getFourBitRandom();
Map map = new HashMap<>();
map.put("code",code);
boolean isSend = msmService.send(map,phone);
if(isSend){
return R.ok();
}else{
return R.error().message("发送短信失败!");
}
}
Service.java
@Override
//发送短信方法
public boolean send(Map map, String phone) {
System.out.println(Sample.keyId+"," + Sample.keySecret);
DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai",Sample.keyId,Sample.keySecret);
IAcsClient client = new DefaultAcsClient(profile);
//登录平台
SendSmsRequest request = new SendSmsRequest();
request.setSignName("阿里云短信测试");
request.setTemplateCode("SMS_154950909");
request.setPhoneNumbers(phone);
String code = (String)map.get("code");
request.setTemplateParam("{"code":"" + code + ""}");
try {
SendSmsResponse response = client.getAcsResponse(request);
System.out.println(new Gson().toJson(response));
} catch (ServerException e) {
e.printStackTrace();
return false;
} catch (ClientException e) {
System.out.println("ErrCode:" + e.getErrCode());
System.out.println("ErrMsg:" + e.getErrMsg());
System.out.println("RequestId:" + e.getRequestId());
return false;
}
return true;
}
这里的keyId和keySecret就是阿里云里面的,上述代码的Sample是自建类,就不列出来了,还有接口部分就省略不贴了。
在swagger进行测试:
不久后手机收到信息,成功



