栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于springboot和redis实现单点登录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于springboot和redis实现单点登录

本文实例为大家分享了基于springboot和redis实现单点登录的具体代码,供大家参考,具体内容如下

1、具体的加密和解密方法

package com.example.demo.util;

import com.google.common.base.Strings;
import sun.misc.base64Decoder;
import sun.misc.base64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;


public class AESUtil {
 private static final String defaultKey = "7bf72345-6266-4381-a4d3-988754c5f9d1";
 
 public static String encryptByDefaultKey(String content) throws Exception {
 return encrypt(content, defaultKey);
 }

 
 
 public static String decryptByDefaultKey(String encryptStr) throws Exception {
 return decrypt(encryptStr, defaultKey);
 }

 

 public static String encrypt(String content, String encryptKey) throws Exception {
 return base64Encode(aesEncryptToBytes(content, encryptKey));

 }

 

 private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {

 KeyGenerator kgen = KeyGenerator.getInstance("AES");

 SecureRandom random;
 if (System.getProperty("os.name").toLowerCase().contains("linux")) {
 random = SecureRandom.getInstance("SHA1PRNG");
 } else {
 random = new SecureRandom();
 }

 random.setSeed(encryptKey.getBytes());
 kgen.init(128, random);

 Cipher cipher = Cipher.getInstance("AES");

 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));


 return cipher.doFinal(content.getBytes("utf-8"));

 }

 

 private static String base64Encode(byte[] bytes) {

 return new base64Encoder().encode(bytes);

 }
 
 

 public static String decrypt(String encryptStr, String decryptKey) throws Exception {

 return Strings.isNullOrEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);

 }
 
 
 private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {

 KeyGenerator kgen = KeyGenerator.getInstance("AES");

 SecureRandom random;
 if (System.getProperty("os.name").toLowerCase().contains("linux")) {
 random = SecureRandom.getInstance("SHA1PRNG");
 } else {
 random = new SecureRandom();
 }
 random.setSeed(decryptKey.getBytes());

 kgen.init(128, random);


 Cipher cipher = Cipher.getInstance("AES");

 cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));

 byte[] decryptBytes = cipher.doFinal(encryptBytes);


 return new String(decryptBytes);

 }

 

 private static byte[] base64Decode(String base64Code) throws Exception {

 return Strings.isNullOrEmpty(base64Code) ? null : new base64Decoder().decodeBuffer(base64Code);

 }
}

2、这里获取的token很关键,每次登录都要生成新的token,token是根据userId和当前时间戳加密的

@Override
 public String getToken(String userId) throws Exception {
 String token = AESUtil.encryptByDefaultKey(Joiner.on("_").join(userId, System.currentTimeMillis()));
 logger.debugv("token= {0}", token);
 redisService.set(UserKey.userAccessKey, userId, token);
 return token;
 }

3、写一个解密的方法,解密把用户id拿出来,然后从拦截器里拿出token和当前登录token做对比

 @Override
 public String checkToken(String token) throws Exception {
 String userId = AESUtil.decryptByDefaultKey(token).split("_")[0];
 String currentToken = redisService.get(UserKey.userAccessKey, userId, String.class);
 logger.debugv("currentToken={0}", currentToken);
 if (StringUtils.isEmpty(currentToken)) {
  return null;
 }
 if (!token.equals(currentToken)) {
  return null;
 }
 return userId;
 }

4、拦截器里具体处理,这里采用注解拦截,当controller有@Secured拦截器才拦截

 @Autowired
 AuthTokenService authTokenService;
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

 if (handler instanceof HandlerMethod) {
  HandlerMethod hm = (HandlerMethod) handler;
  Secured secured = hm.getMethodAnnotation(Secured.class);
  if (secured != null) {
  String authToken = request.getHeader(UserConstant.USER_TOKEN);
  if (StringUtils.isEmpty(authToken)) {
   render(response, CodeMsg.REQUEST_ILLEGAL);
   return false;
  }
  String userId = authTokenService.checkToken(authToken);
  if (StringUtils.isEmpty(userId)) {
   render(response, CodeMsg.LOGIN_FAILURE);
   return false;
  }
  }
  return true;
 }
 return true;
 }


private void render(HttpServletResponse response, CodeMsg cm) throws Exception {
 response.setContentType("application/json;charset=UTF-8");
 OutputStream out = response.getOutputStream();
 String str = JSON.toJSonString(Result.error(cm));
 out.write(str.getBytes("UTF-8"));
 out.flush();
 out.close();
 }

5、写一个测试登录接口和一个测试单点登录接口

 
 @GetMapping("/login")
 public Result login() throws Exception {
 return authTokenService.login();
 }
 
 
 
 @Secured
 @GetMapping("/testSSO")
 public Result testSSO() {
 return authTokenService.testSSO();
 }

 具体的实现
 @Override
 public Result login() throws Exception {
 String userId = "123456";
 return Result.success(this.getToken(userId));
 }

 @Override
 public Result testSSO() {
 return Result.success("登录状态正常");
 }

postman 测试

单点登录测试

再次请求登录接口,然后不改变token接口如图

这个方式实现单点登录的关键就是根据userId的加密和解密的实现。

github地址:demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/137820.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号