最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄

 更新時(shí)間:2019年06月24日 14:37:30   作者:workit123  
這篇文章主要為大家詳細(xì)介紹了基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了基于springboot和redis實(shí)現(xiàn)單點(diǎn)登錄的具體代碼,供大家參考,具體內(nèi)容如下

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;

/**
 * Create by zhuenbang on 2018/12/3 11:27
 */
public class AESUtil {
 private static final String defaultKey = "7bf72345-6266-4381-a4d3-988754c5f9d1";
 /** 
 * @Description: 加密
 * @Param: 
 * @returns: java.lang.String 
 * @Author: zhuenbang
 * @Date: 2018/12/3 11:33
 */
 public static String encryptByDefaultKey(String content) throws Exception {
 return encrypt(content, defaultKey);
 }

 
 /** 
 * @Description: 解密 
 * @Param: 
 * @returns: java.lang.String 
 * @Author: zhuenbang
 * @Date: 2018/12/3 11:30
 */
 public static String decryptByDefaultKey(String encryptStr) throws Exception {
 return decrypt(encryptStr, defaultKey);
 }

 /**
 * AES加密為base 64 code
 *
 * @param content 待加密的內(nèi)容
 * @param encryptKey 加密密鑰
 * @return 加密后的base 64 code
 * @throws Exception
 */

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

 }

 /**
 * AES加密
 *
 * @param content 待加密的內(nèi)容
 * @param encryptKey 加密密鑰
 * @return 加密后的byte[]
 * @throws Exception
 */

 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"));

 }

 /**
 * base 64 加密
 *
 * @param bytes 待編碼的byte[]
 * @return 編碼后的base 64 code
 */

 private static String base64Encode(byte[] bytes) {

 return new BASE64Encoder().encode(bytes);

 }
 
 /**
 * 將base 64 code AES解密
 *
 * @param encryptStr 待解密的base 64 code
 * @param decryptKey 解密密鑰
 * @return 解密后的string
 * @throws Exception
 */

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

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

 }
 
 /**
 * AES解密
 *
 * @param encryptBytes 待解密的byte[]
 * @param decryptKey 解密密鑰
 * @return 解密后的String
 * @throws Exception
 */
 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);

 }

 /**
 * base 64 解密
 *
 * @param base64Code 待解碼的base 64 code
 * @return 解碼后的byte[]
 * @throws Exception
 */

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

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

 }
}

2、這里獲取的token很關(guān)鍵,每次登錄都要生成新的token,token是根據(jù)userId和當(dāng)前時(shí)間戳加密的

@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、寫一個(gè)解密的方法,解密把用戶id拿出來,然后從攔截器里拿出token和當(dāng)前登錄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、攔截器里具體處理,這里采用注解攔截,當(dāng)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、寫一個(gè)測試登錄接口和一個(gè)測試單點(diǎn)登錄接口

 /** 
 * @Description: 模擬登錄 
 * @Param: 
 * @returns: com.example.demo.result.Result 
 * @Author: zhuenbang
 * @Date: 2018/12/3 12:05
 */
 @GetMapping("/login")
 public Result login() throws Exception {
 return authTokenService.login();
 }
 
 
 /** 
 * @Description: 模擬單點(diǎn)登錄 @Secured這個(gè)方法攔截器會攔截
 * @Param: 
 * @returns: com.example.demo.result.Result 
 * @Author: zhuenbang
 * @Date: 2018/12/3 12:35
 */
 @Secured
 @GetMapping("/testSSO")
 public Result testSSO() {
 return authTokenService.testSSO();
 }

 具體的實(shí)現(xiàn)
 @Override
 public Result login() throws Exception {
 String userId = "123456";
 return Result.success(this.getToken(userId));
 }

 @Override
 public Result testSSO() {
 return Result.success("登錄狀態(tài)正常");
 }

postman 測試

單點(diǎn)登錄測試

再次請求登錄接口,然后不改變token接口如圖

這個(gè)方式實(shí)現(xiàn)單點(diǎn)登錄的關(guān)鍵就是根據(jù)userId的加密和解密的實(shí)現(xiàn)。

github地址:demo

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Java Api操作HDFS過程詳解

    使用Java Api操作HDFS過程詳解

    這篇文章主要介紹了使用Java Api操作HDFS過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java程序圖形用戶界面設(shè)計(jì)之按鈕與布局

    Java程序圖形用戶界面設(shè)計(jì)之按鈕與布局

    圖形界面(簡稱GUI)是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。與早期計(jì)算機(jī)使用的命令行界面相比,圖形界面對于用戶來說在視覺上更易于接受,本篇精講Java語言中關(guān)于圖形用戶界面的按鈕和布局部分
    2022-02-02
  • SpringBoot注解生效原理全解析

    SpringBoot注解生效原理全解析

    Spring Boot注解自動生效依賴于Spring容器和處理機(jī)制,通過掃描、解析配置類生成BeanDefinition,再由容器實(shí)例化,實(shí)現(xiàn)@Autowired等注解的自動注入與組件注冊,本文給大家介紹SpringBoot注解生效原理分析,感興趣的朋友一起看看吧
    2025-09-09
  • 整理Java編程中字符串的常用操作方法

    整理Java編程中字符串的常用操作方法

    這篇文章主要介紹了Java編程中字符串的常用操作方法的整理,字符串處理是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2016-02-02
  • 使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)

    使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)

    使用springboot開發(fā)時(shí)經(jīng)常用到@Autowired和@Resource進(jìn)行依賴注入,但是當(dāng)我們一個(gè)接口對應(yīng)多個(gè)不同的實(shí)現(xiàn)類的時(shí)候如果不進(jìn)行一下配置項(xiàng)目啟動時(shí)就會報(bào)錯(cuò),那么怎么根據(jù)不同的需求注入不同的類型呢,感興趣的朋友一起看看吧
    2022-06-06
  • SpringBoot中的bean管理示例詳解

    SpringBoot中的bean管理示例詳解

    這篇文章主要介紹了SpringBoot中的bean管理,本文結(jié)合示例代碼給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • java解一個(gè)比較特殊的數(shù)組合并題

    java解一個(gè)比較特殊的數(shù)組合并題

    這篇文章主要介紹了java解一個(gè)比較特殊的數(shù)組合并題,需要的朋友可以參考下
    2014-06-06
  • mybatis調(diào)用存儲過程,帶in、out參數(shù)問題

    mybatis調(diào)用存儲過程,帶in、out參數(shù)問題

    這篇文章主要介紹了mybatis調(diào)用存儲過程,帶in、out參數(shù)問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 詳解JAVA 內(nèi)存管理

    詳解JAVA 內(nèi)存管理

    這篇文章主要介紹了JAVA 內(nèi)存管理的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • java實(shí)現(xiàn)掃雷游戲

    java實(shí)現(xiàn)掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04

最新評論

土默特右旗| 茂名市| 岳普湖县| 蒙城县| 香格里拉县| 灯塔市| 高清| 喀喇| 隆安县| 肥乡县| 灵丘县| 沁源县| 通海县| 菏泽市| 资中县| 云南省| 建平县| 巫山县| 当雄县| 阿克陶县| 旬阳县| 绥江县| 桐梓县| 花莲市| 卓尼县| 荥经县| 贵阳市| 兴城市| 新龙县| 正镶白旗| 延吉市| 永登县| 阿勒泰市| 曲沃县| 白沙| 静海县| 确山县| 阿城市| 天等县| 盐城市| 老河口市|