日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

完成单点登录

發(fā)布時(shí)間:2024/4/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 完成单点登录 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

編寫登錄接口

接下來,我們需要在auth編寫一個(gè)接口,對外提供登錄授權(quán)服務(wù)。基本流程如下:

  • 客戶端攜帶用戶名和密碼請求登錄

  • 授權(quán)中心調(diào)用用戶中心接口,根據(jù)用戶名和密碼查詢用戶信息

  • 如果用戶名密碼正確,能獲取用戶,否則登錄失敗

  • 如果校驗(yàn)成功,則生成JWT并返回

編寫遠(yuǎn)程調(diào)用接口

創(chuàng)建ums-interface工程:

pom.xml中的依賴,參照其他interface工程。并在ums和auth工程中引入該接口工程

UmsApi:

public interface UmsApi {/*** 根據(jù)用戶名和密碼查詢用戶* @param username* @param password* @return*/@GetMapping("ums/member/query")public Resp<MemberEntity> queryUser(@RequestParam("username") String username,@RequestParam("password") String password); }

生成公鑰和私鑰

我們需要在授權(quán)中心生成真正的公鑰和私鑰。我們必須有一個(gè)生成公鑰和私鑰的secret,這個(gè)可以配置到application.yml中:

jwt:pubKeyPath: C:\\tmp\\rsa\\rsa.pub # 公鑰地址priKeyPath: C:\\tmp\\rsa\\rsa.pri # 私鑰地址secret: sf3423jsdf#3$@FDS32expire: 30 # 過期時(shí)間,單位分鐘cookieName: TOKEN

然后編寫屬性類讀取jwt配置,并從秘鑰配置文件中讀取出響應(yīng)的公鑰及私鑰,加載這些數(shù)據(jù):

@Data @Slf4j @ConfigurationProperties(prefix = "jwt") public class JwtProperties {private String secret; // 密鑰private String pubKeyPath;// 公鑰private String priKeyPath;// 私鑰private int expire;// token過期時(shí)間private PublicKey publicKey; // 公鑰private PrivateKey privateKey; // 私鑰private String cookieName; // cookie名稱/*** @PostContruct:在構(gòu)造方法執(zhí)行之后執(zhí)行該方法*/@PostConstructpublic void init() {try {File pubKey = new File(pubKeyPath);File priKey = new File(priKeyPath);if (!pubKey.exists() || !priKey.exists()) {// 生成公鑰和私鑰RsaUtils.generateKey(pubKeyPath, priKeyPath, secret);}// 獲取公鑰和私鑰this.publicKey = RsaUtils.getPublicKey(pubKeyPath);this.privateKey = RsaUtils.getPrivateKey(priKeyPath);} catch (Exception e) {log.error("初始化公鑰和私鑰失敗!", e);throw new RuntimeException();}} }

AuthController

編寫授權(quán)接口,我們接收用戶名和密碼,校驗(yàn)成功后,寫入cookie中。

  • 請求方式:post

  • 請求路徑:/auth/accredit

  • 請求參數(shù):username和password

  • 返回結(jié)果:無

代碼:

@RestController @RequestMapping("auth") @EnableConfigurationProperties(JwtProperties.class) public class AuthController {@Autowiredprivate AuthService authService;@Autowiredprivate JwtProperties jwtProperties;/*** 登錄授權(quán)** @param username* @param password* @return*/@PostMapping("accredit")public Resp<Object> authentication(@RequestParam("username") String username,@RequestParam("password") String password,HttpServletRequest request,HttpServletResponse response) {// 登錄校驗(yàn)String token = this.authService.authentication(username, password);if (StringUtils.isBlank(token)) {return Resp.fail("登錄失敗,用戶名或密碼錯(cuò)誤");}// 將token寫入cookie,并指定httpOnly為true,防止通過JS獲取和修改CookieUtils.setCookie(request, response, jwtProperties.getCookieName(), token, jwtProperties.getExpire());return Resp.ok("登錄成功");} }

AuthService

在auth-service:

@Service public class AuthService {@Autowiredprivate UmsClient umsClient;@Autowiredprivate JwtProperties jwtProperties;public String authentication(String username, String password) {try {// 調(diào)用微服務(wù),執(zhí)行查詢Resp<MemberEntity> resp = this.umsClient.queryUser(username, password);MemberEntity memberEntity = resp.getData();// 如果查詢結(jié)果為null,則直接返回nullif (memberEntity == null) {return null;}// 如果有查詢結(jié)果,則生成tokenMap<String, Object> map = new HashMap<>();map.put("id", memberEntity.getId());map.put("username", memberEntity.getUsername());String token = JwtUtils.generateToken(map, jwtProperties.getPrivateKey(), jwtProperties.getExpire());return token;} catch (Exception e) {e.printStackTrace();}return null;} }

UmsClient

接下來我們肯定要對用戶密碼進(jìn)行校驗(yàn),所以我們需要通過FeignClient去訪問 ums-service微服務(wù):

在auth中引入ums-interface依賴:

<dependency><groupId>com.atguigu</groupId><artifactId>ums-interface</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>

編寫UmsClient:

@FeignClient("ums-service") public interface UmsClient extends UmsApi { }

CookieUtils

要注意,這里我們使用了一個(gè)工具類,CookieUtils,可以在課前資料中找到,我們把它添加到core中,然后引入servlet相關(guān)依賴即可:

package com.leon.core.utils;import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder;/*** * Cookie 工具類**/ public final class CookieUtils {static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);/*** 得到Cookie的值, 不編碼* * @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName) {return getCookieValue(request, cookieName, false);}/*** 得到Cookie的值,* * @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null){return null; }String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {if (isDecoder) {retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");} else {retValue = cookieList[i].getValue();}break;}}} catch (UnsupportedEncodingException e) {logger.error("Cookie Decode Error.", e);}return retValue;}/*** 得到Cookie的值,* * @param request* @param cookieName* @return*/public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {Cookie[] cookieList = request.getCookies();if (cookieList == null || cookieName == null){return null; }String retValue = null;try {for (int i = 0; i < cookieList.length; i++) {if (cookieList[i].getName().equals(cookieName)) {retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);break;}}} catch (UnsupportedEncodingException e) {logger.error("Cookie Decode Error.", e);}return retValue;}/*** 生成cookie,并指定編碼* @param request 請求* @param response 響應(yīng)* @param cookieName name* @param cookieValue value* @param encodeString 編碼*/public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, String encodeString) {setCookie(request,response,cookieName,cookieValue,null,encodeString, null);}/*** 生成cookie,并指定生存時(shí)間* @param request 請求* @param response 響應(yīng)* @param cookieName name* @param cookieValue value* @param cookieMaxAge 生存時(shí)間*/public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge) {setCookie(request,response,cookieName,cookieValue,cookieMaxAge,null, null);}/*** 設(shè)置cookie,不指定httpOnly屬性*/public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString) {setCookie(request,response,cookieName,cookieValue,cookieMaxAge,encodeString, null);}/*** 設(shè)置Cookie的值,并使其在指定時(shí)間內(nèi)生效* * @param cookieMaxAge* cookie生效的最大秒數(shù)*/public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString, Boolean httpOnly) {try {if(StringUtils.isBlank(encodeString)) {encodeString = "utf-8";}if (cookieValue == null) {cookieValue = "";} else {cookieValue = URLEncoder.encode(cookieValue, encodeString);}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxAge != null && cookieMaxAge > 0)cookie.setMaxAge(cookieMaxAge);if (null != request)// 設(shè)置域名的cookiecookie.setDomain(getDomainName(request));cookie.setPath("/");if(httpOnly != null) {cookie.setHttpOnly(httpOnly);}response.addCookie(cookie);} catch (Exception e) {logger.error("Cookie Encode Error.", e);}}/*** 得到cookie的域名*/private static final String getDomainName(HttpServletRequest request) {String domainName = null;String serverName = request.getRequestURL().toString();if (serverName == null || serverName.equals("")) {domainName = "";} else {serverName = serverName.toLowerCase();serverName = serverName.substring(7);final int end = serverName.indexOf("/");serverName = serverName.substring(0, end);final String[] domains = serverName.split("\\.");int len = domains.length;if (len > 3) {// www.xxx.com.cndomainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];} else if (len <= 3 && len > 1) {// xxx.com or xxx.cndomainName = domains[len - 2] + "." + domains[len - 1];} else {domainName = serverName;}}if (domainName != null && domainName.indexOf(":") > 0) {String[] ary = domainName.split("\\:");domainName = ary[0];}return domainName;}}

?

超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的完成单点登录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。