欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

SpringCloud實現(xiàn)SSO單點登錄的示例代碼

前言

創(chuàng)新互聯(lián)建站是一家專業(yè)提供平陰企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站制作、成都網(wǎng)站制作、HTML5建站、小程序制作等業(yè)務(wù)。10年已為平陰眾多企業(yè)、政府機構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進行中。

作為分布式項目,單點登錄是必不可少的,文本基于之前的的博客(猛戳:SpringCloud系列——Zuul 動態(tài)路由,SpringBoot系列——redis)記錄Zuul配合Redis實現(xiàn)一個簡單的sso單點登錄實例

sso單點登錄思路:

1、訪問分布式系統(tǒng)的任意請求,被Zuul的Filter攔截過濾

2、在run方法里實現(xiàn)過濾規(guī)則:cookie有令牌accessToken且作為key存在于Redis,或者訪問的是登錄頁面、登錄請求則放行

3、否則,將重定向到sso-server的登錄頁面且原先的請求路徑作為一個參數(shù);response.sendRedirect("http://localhost:10010/sso-server/sso/loginPage?url=" + url);

4、登錄成功,sso-server生成accessToken,并作為key(用戶名+時間戳,這里只是demo,正常項目的令牌應(yīng)該要更為復(fù)雜)存到Redis,value值存用戶id作為value(或者直接存儲可暴露的部分用戶信息也行)設(shè)置過期時間(我這里設(shè)置3分鐘);設(shè)置cookie:new Cookie("accessToken",accessToken);,設(shè)置maxAge(60*3);、path("/");

5、sso-server單點登錄服務(wù)負(fù)責(zé)校驗用戶信息、獲取用戶信息、操作Redis緩存,提供接口,在eureka上注冊

代碼編寫

sso-server

首先我們創(chuàng)建一個單點登錄服務(wù)sso-server,并在eureka上注冊(創(chuàng)建項目請參考之前的SpringCloud系列博客跟SpringBoot系列——Redis)

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

login.html

我們這里需要用到頁面,要先maven引入thymeleaf

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>登錄頁面</title>
</head>
<body>
 <form action="/sso-server/sso/login" method="post">
  <input name="url" type="hidden" th:value="${url}"/>
  用戶名:<input name="username" type="text"/>
  密碼:<input name="password" type="password"/>
  <input value="登錄" type="submit"/>
 </form>
</body>
</html>

提供如下接口

@RestController
@EnableEurekaClient
@SpringBootApplication
public class SsoServerApplication {

 public static void main(String[] args) {
  SpringApplication.run(SsoServerApplication.class, args);
 }

 @Autowired
 private StringRedisTemplate template;

 /**
  * 判斷key是否存在
  */
 @RequestMapping("/redis/hasKey/{key}")
 public Boolean hasKey(@PathVariable("key") String key) {
  try {
   return template.hasKey(key);
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }

 /**
  * 校驗用戶名密碼,成功則返回通行令牌(這里寫死huanzi/123456)
  */
 @RequestMapping("/sso/checkUsernameAndPassword")
 private String checkUsernameAndPassword(String username, String password) {
  //通行令牌
  String flag = null;
  if ("huanzi".equals(username) && "123456".equals(password)) {
   //用戶名+時間戳(這里只是demo,正常項目的令牌應(yīng)該要更為復(fù)雜)
   flag = username + System.currentTimeMillis();
   //令牌作為key,存用戶id作為value(或者直接存儲可暴露的部分用戶信息也行)設(shè)置過期時間(我這里設(shè)置3分鐘)
   template.opsForValue().set(flag, "1", (long) (3 * 60), TimeUnit.SECONDS);
  }
  return flag;
 }

 /**
  * 跳轉(zhuǎn)登錄頁面
  */
 @RequestMapping("/sso/loginPage")
 private ModelAndView loginPage(String url) {
  ModelAndView modelAndView = new ModelAndView("login");
  modelAndView.addObject("url", url);
  return modelAndView;
 }

 /**
  * 頁面登錄
  */
 @RequestMapping("/sso/login")
 private String login(HttpServletResponse response, String username, String password, String url) {
  String check = checkUsernameAndPassword(username, password);
  if (!StringUtils.isEmpty(check)) {
   try {
    Cookie cookie = new Cookie("accessToken", check);
    cookie.setMaxAge(60 * 3);
    //設(shè)置域
//    cookie.setDomain("huanzi.cn");
    //設(shè)置訪問路徑
    cookie.setPath("/");
    response.addCookie(cookie);
    //重定向到原先訪問的頁面
    response.sendRedirect(url);
   } catch (IOException e) {
    e.printStackTrace();
   }
   return null;
  }
  return "登錄失敗";
 }
}

zuul-server

引入feign,用于調(diào)用sso-server服務(wù)

 <!-- feign -->
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>

創(chuàng)建SsoFeign.java接口

@FeignClient(name = "sso-server", path = "/")
public interface SsoFeign {
 /**
  * 判斷key是否存在
  */
 @RequestMapping("redis/hasKey/{key}")
 public Boolean hasKey(@PathVariable("key") String key);

}

啟動類加入@EnableFeignClients注解,否則啟動會報錯,無法注入SsoFeign對象

@EnableZuulProxy
@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class ZuulServerApplication {

 public static void main(String[] args) {
  SpringApplication.run(ZuulServerApplication.class, args);
 }

 @Bean
 public AccessFilter accessFilter() {
  return new AccessFilter();
 }
}

修改AccessFilter過濾邏輯,注入feign接口,用于調(diào)用sso-server檢查Redis,修改run方法的過濾邏輯

/**
 * Zuul過濾器,實現(xiàn)了路由檢查
 */
public class AccessFilter extends ZuulFilter {

 @Autowired
 private SsoFeign ssoFeign;

 /**
  * 通過int值來定義過濾器的執(zhí)行順序
  */
 @Override
 public int filterOrder() {
  // PreDecoration之前運行
  return PRE_DECORATION_FILTER_ORDER - 1;
 }

 /**
  * 過濾器的類型,在zuul中定義了四種不同生命周期的過濾器類型:
  * public static final String ERROR_TYPE = "error";
  * public static final String POST_TYPE = "post";
  * public static final String PRE_TYPE = "pre";
  * public static final String ROUTE_TYPE = "route";
  */
 @Override
 public String filterType() {
  return PRE_TYPE;
 }

 /**
  * 過濾器的具體邏輯
  */
 @Override
 public Object run() {
  RequestContext ctx = RequestContext.getCurrentContext();
  HttpServletRequest request = ctx.getRequest();
  HttpServletResponse response = ctx.getResponse();

  //訪問路徑
  String url = request.getRequestURL().toString();

  //從cookie里面取值(Zuul丟失Cookie的解決方案:https://blog.csdn.net/lindan1984/article/details/79308396)
  String accessToken = request.getParameter("accessToken");
  for (Cookie cookie : request.getCookies()) {
   if ("accessToken".equals(cookie.getName())) {
    accessToken = cookie.getValue();
   }
  }
  //過濾規(guī)則:cookie有令牌且存在于Redis,或者訪問的是登錄頁面、登錄請求則放行
  if (url.contains("sso-server/sso/loginPage") || url.contains("sso-server/sso/login") || (!StringUtils.isEmpty(accessToken) && ssoFeign.hasKey(accessToken))) {
   ctx.setSendZuulResponse(true);
   ctx.setResponseStatusCode(200);
   return null;
  } else {
   ctx.setSendZuulResponse(false);
   ctx.setResponseStatusCode(401);
   //重定向到登錄頁面
   try {
    response.sendRedirect("http://localhost:10010/sso-server/sso/loginPage?url=" + url);
   } catch (IOException e) {
    e.printStackTrace();
   }
   return null;
  }
 }

 /**
  * 返回一個boolean類型來判斷該過濾器是否要執(zhí)行
  */
 @Override
 public boolean shouldFilter() {
  return true;
 }
}

修改配置文件,映射sso-server代理路徑,超時時間與丟失cookie的解決

zuul.routes.sso-server.path=/sso-server/**
zuul.routes.sso-server.service-id=sso-server


zuul.host.socket-timeout-millis=60000
zuul.host.connect-timeout-millis=10000
#Zuul丟失Cookie的解決方案:https://blog.csdn.net/lindan1984/article/details/79308396
zuul.sensitive-headers=

測試效果

啟動eureka、zuul-server、sso-server、config-server、myspringboot、springdatajpa(由兩個應(yīng)用組成,實現(xiàn)了ribbon負(fù)載均衡),記得啟動我們的RabbitMQ服務(wù)和Redis服務(wù)!

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

剛開始,沒有cookie且無Redis的情況下,瀏覽器訪問http://localhost:10010/myspringboot/feign/ribbon,被zuul-server攔截重定向到sso-server登錄頁面

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

開始登錄校驗,為了方便演示,我將密碼的type改成text

登錄失敗,返回提示語

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

登錄成功,重定向到之前的請求

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

cookie的值,以及過期時間

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

3分鐘后我們再次訪問http://localhost:10010/myspringboot/feign/ribbon,cookie、Redis失效,需要從新登錄

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

SpringCloud實現(xiàn)SSO 單點登錄的示例代碼

后記

sso單點登錄就記錄到這里,這里只是實現(xiàn)了單機版的sso,以后在進行升級吧。

問題報錯:我們在sso-server設(shè)置cookie后,在zuul-server的run方法里獲取不到設(shè)置的cookie,去瀏覽器查看,cookie沒有設(shè)置成功,Zuul丟失Cookie

解決方案

我們是使用spring cloud zuul作為api-gateway實踐中,發(fā)現(xiàn)默認(rèn)zuul會過濾掉cookie等header信息,有些業(yè)務(wù)場景需要傳遞這些信息該怎么處理呢?

處理方式   在api-gateway的application.properties文件中添加 zuul.sensitive-headers=  

問題原因

負(fù)責(zé)根據(jù)ServiceId來路由的RibbonRoutingFilter在route之前會調(diào)用ProxyRequestHelper的buildZuulRequestHeaders(request)來重新組裝一個新的Header。

在buildZuulRequestHeaders方法中會對RequsetHeader中的每一項調(diào)用isIncludedHeader(name)來判斷當(dāng)前項是否應(yīng)該留在新的Header中,如下圖,如果當(dāng)前項在IGNORED_HEADERS(需要忽略的信息)中,就不會在新header中保留。

PreDecorationFilter過濾器會調(diào)用ProxyRequestHelper的addIgnoredHeaders方法把敏感信息(ZuulProperties的sensitiveHeaders屬性)添加到請求上下文的IGNORED_HEADERS中

sensitiveHeaders的默認(rèn)值初始值是"Cookie", "Set-Cookie", "Authorization"這三項,可以看到Cookie被列為了敏感信息,所以不會放到新header中

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)頁名稱:SpringCloud實現(xiàn)SSO單點登錄的示例代碼
URL分享:http://aaarwkj.com/article48/gjohep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、小程序開發(fā)、云服務(wù)器、用戶體驗、ChatGPT、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
91午夜福利国产在线观看 | av午夜精品一区二区| 日韩精品免费一区二区三区| 成人性生交大片免费男同| 亚洲毛片在线免费播放| 日本精品专区在线观看| 精品国产视频一区二区三区| 91国产网址在线观看| 激情啪啪啪的免费网站| 91人妻一区二区三区久久| 一区二区日韩激情在线观看视频| 夫妻性生活一级片视频| 97视频免费观看在线| 成人性生交大片免费男同| 欧美一区二区三区人妻激情| 黄片大全在线免费视频观看| 国产成人免费高清av| 天天操天天射夜夜撸| 久久热福利视频就在这里| 四虎在线观看最新入口| 日本午夜激情一区二区| 成人av资源在线观看| 中文成人无字幕乱码精品| 人妻天天爽夜夜爽欧美色| 免费在线观看性生活视频| 粗暴蹂躏中文一区二区三区| 麻豆精品人妻中文在线| 国内揄拍国内精品对久久| 香蕉久草官网视频观看| 人妻有码系列中文字幕专区| 日韩精品国产亚洲欧美| 高清不卡一区二区在线观看| 水蜜桃在线观看一区二区国产 | 丰满人妻一区二区三区免费| 欧美午夜一区二区电影| 久草福利在线观看免费| 中文字幕日韩不卡顿一区二区| 亚洲午夜av久久乱码| 午夜影院网站在线看黄| 91精品国产高清一区二区性色| 日韩在线啊啊啊的视频|