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

SpringBoot整合SSO(single sign on)單點(diǎn)登錄

 更新時(shí)間:2020年06月17日 12:05:29   作者:Mr Kwan  
這篇文章主要介紹了SpringBoot整合SSO(single sign on)單點(diǎn)登錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、單點(diǎn)登錄三種常見的方式

(1)Session廣播機(jī)制(Session復(fù)制)
(2)使用Cookie+Redis實(shí)現(xiàn)
(3)使用token實(shí)現(xiàn)


2、單點(diǎn)登錄介紹





舉例:


(1)引入jwt依賴

 <!-- JWT-->
<dependency>
 <groupId>io.jsonwebtoken</groupId>
 <artifactId>jjwt</artifactId>
</dependency>

(2)創(chuàng)建JWTUtils工具類

public class JwtUtils {

 //token過期時(shí)間
 public static final long EXPIRE = 1000 * 60 * 60 * 24;
 //秘鑰
 public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";

 public static String getJwtToken(String id, String nickname){

  String JwtToken = Jwts.builder()
    //設(shè)置頭信息
    .setHeaderParam("typ", "JWT")
    .setHeaderParam("alg", "HS256")
    .setSubject("user")
    .setIssuedAt(new Date())
    //設(shè)置過期時(shí)間
    .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
    //設(shè)置token主體部分(這里使用id和nickname作為主體部分)
    .claim("id", id)
    .claim("nickname", nickname)
    //加密方式
    .signWith(SignatureAlgorithm.HS256, APP_SECRET)
    .compact();

  return JwtToken;
 }

 /**
  * 判斷token是否存在與有效(直接通過APP_SECRET解析token)
  * @param jwtToken
  * @return
  */
 public static boolean checkToken(String jwtToken) {
  if(StringUtils.isEmpty(jwtToken)) return false;
  try {
   Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
  return true;
 }

 /**
  * 判斷token是否存在與有效(通過獲取請(qǐng)求頭信息獲取token再使用APP_SECRET解析token)
  * @param request
  * @return
  */
 public static boolean checkToken(HttpServletRequest request) {
  try {
   String jwtToken = request.getHeader("token");
   if(StringUtils.isEmpty(jwtToken)) return false;
   Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
  return true;
 }

 /**
  * 根據(jù)token字符串獲取用戶id(取出有效載荷中的用戶信息)
  * @param request
  * @return
  */
 public static String getMemberIdByJwtToken(HttpServletRequest request) {
  String jwtToken = request.getHeader("token");
  if(StringUtils.isEmpty(jwtToken)) return "";
  Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
  Claims claims = claimsJws.getBody();
  return (String)claims.get("id");
 }
}

3、單點(diǎn)登錄實(shí)現(xiàn)

項(xiàng)目目錄結(jié)構(gòu)


UcenterMemberController

@RestController
@RequestMapping("/user/")
@CrossOrigin
public class UcenterMemberController {

 @Autowired
 private UcenterMemberService ucenterMemberService;
	//登錄
 @PostMapping("login")
 public ResponseResult login(@RequestBody MobileLoginRequest request) {
  String token = ucenterMemberService.login(request);
  return ResponseResult.success().data("token", token);
 }
	//注冊(cè)
 @PostMapping("register")
 public ResponseResult register(@RequestBody RegisterRequest request) {
  ucenterMemberService.register(request);
  return ResponseResult.success().message("注冊(cè)成功");
 }
	//根據(jù)token獲取用戶信息
 @GetMapping("getUserInfo")
 public ResponseResult getUserInfo(HttpServletRequest request) {
  //調(diào)用jwt工具類的方法,根據(jù)request對(duì)象獲取頭信息,返回用戶id
  String id = JwtUtils.getMemberIdByJwtToken(request);
  //根據(jù)用戶id查詢用戶
  UcenterMember member = ucenterMemberService.getById(id);
  return ResponseResult.success().data("userInfo", member);
 }

}

ServiceImpl

@Service
public class UcenterMemberServiceImpl extends ServiceImpl<UcenterMemberMapper, UcenterMember> implements UcenterMemberService {

 @Autowired
 private StringRedisTemplate redisTemplate;

	//登錄
 @Override
 public String login(MobileLoginRequest request) {

  String phone = request.getPhone();
  String password = request.getPassword();
  if (StrUtil.isBlank(phone) || StrUtil.isBlank(password)) {
   throw new GuliException(200001, "請(qǐng)輸入用戶名或者密碼");
  }
  //根據(jù)輸入的手機(jī)號(hào)碼查找該用戶信息
  UcenterMember ucenterByPhone = this.baseMapper.selectOne(new LambdaQueryWrapper<UcenterMember>().eq(UcenterMember::getMobile, phone));
  if (ucenterByPhone == null) {
   throw new GuliException(200002, "該用戶名不存在");
  }
  //如果用戶存在比對(duì)數(shù)據(jù)庫(kù)密碼和用戶輸入的密碼
  if (!MD5Util.encrypt(password).equals(ucenterByPhone.getPassword())) {
   throw new GuliException(200003, "密碼輸入錯(cuò)誤");
  }
  String token = JwtUtils.getJwtToken(ucenterByPhone.getId(), ucenterByPhone.getNickname());
  return token;
 }

	//注冊(cè)
 @Override
 public void register(RegisterRequest request) {
  String phone = request.getPhone();
  String password = request.getPassword();
  String nickName = request.getNickName();
  String code = request.getCode();
  if (StrUtil.isBlank(phone) || StrUtil.isBlank(password) || StrUtil.isBlank(nickName) || StrUtil.isBlank(code)) {
   throw new GuliException(200001, "請(qǐng)?zhí)顚懴嚓P(guān)信息");
  }
  //判斷手機(jī)號(hào)是否重復(fù)
  Integer count = baseMapper.selectCount(new LambdaQueryWrapper<UcenterMember>().eq(UcenterMember::getMobile, phone));
  if (count > 0) {
   throw new GuliException(200001, "賬號(hào)已經(jīng)存在請(qǐng)重新輸入");
  }
  //驗(yàn)證code
  String redisCode = redisTemplate.opsForValue().get(phone);
  if (StrUtil.isBlank(redisCode)) {
   throw new GuliException(200001, "驗(yàn)證碼已經(jīng)過期,請(qǐng)重新獲取");
  }
  if (!redisCode.equals(code)) {
   throw new GuliException(200001, "驗(yàn)證碼錯(cuò)誤");
  }

  UcenterMember ucenterByPhone = new UcenterMember();
  ucenterByPhone.setMobile(phone);
  ucenterByPhone.setPassword(MD5Util.encrypt(password));
  ucenterByPhone.setNickname(nickName);
  ucenterByPhone.setIsDisabled(false);
  int insert = baseMapper.insert(ucenterByPhone);
  if(insert<=0){
   throw new GuliException(20001,"注冊(cè)失敗");
  }
 }
}

MD5加密算法工具類

public final class MD5Util {

 public static String encrypt(String strSrc) {
  try {
   char hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
     '9', 'a', 'b', 'c', 'd', 'e', 'f'};
   byte[] bytes = strSrc.getBytes();
   MessageDigest md = MessageDigest.getInstance("MD5");
   md.update(bytes);
   bytes = md.digest();
   int j = bytes.length;
   char[] chars = new char[j * 2];
   int k = 0;
   for (int i = 0; i < bytes.length; i++) {
    byte b = bytes[i];
    chars[k++] = hexChars[b >>> 4 & 0xf];
    chars[k++] = hexChars[b & 0xf];
   }
   return new String(chars);
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
   throw new RuntimeException("MD5加密出錯(cuò)?。?" + e);
  }
 }

 public static void main(String[] args) {
  System.out.println(MD5Util.encrypt("111111"));
 }

}

4、登錄完成后在前端界面展示用戶信息


(1)第一、二、四步:登錄的方法(記得npm install js-cookie)

 //登錄的方法
  submitLogin() {
  //第一步 調(diào)用接口進(jìn)行登錄,返回token字符串
  loginApi.submitLoginUser(this.user) 
   .then(response => {
    //第二步 獲取token字符串放到cookie里面
    //第一個(gè)參數(shù)cookie名稱,第二個(gè)參數(shù)值,第三個(gè)參數(shù)作用范圍
    cookie.set('user_token',response.data.data.token,{domain: 'localhost'})
    
    //第四步 調(diào)用接口 根據(jù)token獲取用戶信息,為了首頁(yè)面顯示
    loginApi.getLoginUserInfo()
    .then(response => {
     this.loginInfo = response.data.data.userInfo
     //獲取返回用戶信息,放到cookie里面(主頁(yè)在cookie中獲取用戶信息進(jìn)行展示)
     cookie.set('user_info',this.loginInfo,{domain: 'localhost'})

     //跳轉(zhuǎn)頁(yè)面
     window.location.href = "/";
    })
   })
  },

(2)第三步:在request.js中編寫前端請(qǐng)求攔截器(發(fā)送請(qǐng)求攜帶token)

// 創(chuàng)建axios實(shí)例
const service = axios.create({
 baseURL: process.env.BASE_API, // api 的 base_url
 timeout: 5000 // 請(qǐng)求超時(shí)時(shí)間
})

// request攔截器
service.interceptors.request.use(
 config => {
 if (cookie.get('user_token')) {
  config.headers['token'] = cookie.get('user_token') // 讓每個(gè)請(qǐng)求攜帶自定義token 請(qǐng)根據(jù)實(shí)際情況自行修改
 }
 return config
 },
 error => {
 // Do something with request error
 console.log(error) // for debug
 Promise.reject(error)
 }
)

(3)第五步:主頁(yè)顯示用戶信息(從cookie中獲取用戶信息)

//創(chuàng)建方法,從cookie獲取用戶信息
showInfo() {
 //從cookie獲取用戶信息
 var userStr = cookie.get('guli_ucenter')
 // 把字符串轉(zhuǎn)換json對(duì)象(js對(duì)象),因?yàn)楹蠖藗鬟^來的是"{'name','lucy','age':18}"的格式
 if(userStr) {
 this.loginInfo = JSON.parse(userStr)
 }
}

顯示用戶信息(根據(jù)userInfo中id來判斷)

<ul class="h-r-login">
 //cookie中沒有用戶信息,顯示登錄和注冊(cè)
 <li v-if="!loginInfo.id" id="no-login">
  <a href="/login" rel="external nofollow" title="登錄">
   <em class="icon18 login-icon">&nbsp;</em>
   <span class="vam ml5">登錄</span>
  </a>
  |
  <a href="/register" rel="external nofollow" title="注冊(cè)">
   <span class="vam ml5">注冊(cè)</span>
  </a>
 </li>
 //cookie中有用戶信息,顯示用戶頭像、昵稱和退出
 <li v-if="loginInfo.id" id="is-login-two" class="h-r-user">
  <a href="/ucenter" rel="external nofollow" title>
   <img
     :src="loginInfo.avatar"
     width="30"
     height="30"
     class="vam picImg"
     alt
     >
   <span id="userName" class="vam disIb">{{ loginInfo.nickname }}</span>
  </a>
  <a href="javascript:void(0);" rel="external nofollow" title="退出" @click="logout()" class="ml5">退出</a>
 </li>
</ul>

退出登錄,清空cookie中的token和用戶信息

 //退出
 logout() {
  //清空cookie值
  cookie.set('user_token','',{domain: 'localhost'})
  cookie.set('user_info','',{domain: 'localhost'})
  //回到首頁(yè)面
  window.location.href = "/";
 }
 }

到此這篇關(guān)于SpringBoot整合SSO(single sign on)單點(diǎn)登錄的文章就介紹到這了,更多相關(guān)SpringBoot整合SSO單點(diǎn)登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Java設(shè)計(jì)模式之單例模式

    詳解Java設(shè)計(jì)模式之單例模式

    單例模式是一種創(chuàng)建型設(shè)計(jì)模式,它的目的是確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)來訪問該實(shí)例,在單例模式中,類自身負(fù)責(zé)創(chuàng)建自己的唯一實(shí)例,并確保在系統(tǒng)中只有一個(gè)實(shí)例存在,本文詳細(xì)介紹了Java設(shè)計(jì)模式中的單例模式,感興趣的同學(xué)可以參考閱讀
    2023-05-05
  • Java方法的參數(shù)傳遞機(jī)制詳解

    Java方法的參數(shù)傳遞機(jī)制詳解

    這篇文章主要介紹了Java方法的參數(shù)傳遞機(jī)制詳解,對(duì)于Java初學(xué)者來說,剛學(xué)習(xí)Java的時(shí)候可能經(jīng)常會(huì)聽到調(diào)用方法時(shí)參數(shù)的值傳遞與引用傳遞,但是,實(shí)際上Java中方法的參數(shù)傳遞機(jī)制只有值傳遞,需要的朋友可以參考下
    2024-01-01
  • mybatis-generator-gui 工具使用(圖形化工具)

    mybatis-generator-gui 工具使用(圖形化工具)

    基于 mybatis generator 開發(fā)一款界面工具, 本工具可以使你非常容易及快速生成 Mybatis 的 Java POJO 文件及數(shù)據(jù)庫(kù) Mapping 文件。本文重點(diǎn)給大家介紹mybatis-generator-gui 工具使用,感興趣的朋友一起看看吧
    2022-03-03
  • ScheduledExecutorService任務(wù)定時(shí)代碼示例

    ScheduledExecutorService任務(wù)定時(shí)代碼示例

    這篇文章主要介紹了ScheduledExecutorService任務(wù)定時(shí)代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服

    Maven配置中repositories、distributionManagement、pluginRepositori

    這篇文章主要介紹了Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • java模擬http請(qǐng)求的錯(cuò)誤問題整理

    java模擬http請(qǐng)求的錯(cuò)誤問題整理

    本文是小編給大家整理的在用java模擬http請(qǐng)求的時(shí)候遇到的錯(cuò)誤問題整理,以及相關(guān)分析,有興趣的朋友參考下。
    2018-05-05
  • java中List集合子類特點(diǎn)淺析

    java中List集合子類特點(diǎn)淺析

    java.util.List接口繼承自Collection接口,是單列集合的一個(gè)重要分支,習(xí)慣性地會(huì)將實(shí)現(xiàn)了List接口的對(duì)象稱為L(zhǎng)ist集合,下面這篇文章主要給大家介紹了關(guān)于java中List集合子類特點(diǎn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • JSch教程使用sftp協(xié)議實(shí)現(xiàn)服務(wù)器文件載操作

    JSch教程使用sftp協(xié)議實(shí)現(xiàn)服務(wù)器文件載操作

    這篇文章主要為大家介紹了JSch如何使用sftp協(xié)議實(shí)現(xiàn)服務(wù)器文件上傳下載操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • 基于SpringBoot的Docker部署實(shí)踐

    基于SpringBoot的Docker部署實(shí)踐

    在云計(jì)算和微服務(wù)架構(gòu)日益普及的今天,Docker已成為一種主流的應(yīng)用部署方式,本文將詳細(xì)介紹如何將基于Spring Boot的項(xiàng)目部署到Docker容器中,需要的朋友可以參考下
    2023-07-07
  • Java Swing JButton按鈕的實(shí)現(xiàn)示例

    Java Swing JButton按鈕的實(shí)現(xiàn)示例

    這篇文章主要介紹了Java Swing JButton按鈕的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論

新巴尔虎右旗| 登封市| 古田县| 哈密市| 德庆县| 清丰县| 广汉市| 黑龙江省| 德江县| 阳江市| 仁寿县| 莫力| 子长县| 井陉县| 龙江县| 阿鲁科尔沁旗| 基隆市| 老河口市| 柯坪县| 大宁县| 房产| 三明市| 衡南县| 邵阳县| 文成县| 突泉县| 永昌县| 始兴县| 黔西县| 建瓯市| 黄大仙区| 同仁县| 丹巴县| 遂平县| 博客| 万山特区| 黔南| 中西区| 中江县| 大石桥市| 涿州市|