欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot+JWT實(shí)現(xiàn)單點(diǎn)登錄完美解決方案

 更新時(shí)間:2023年07月05日 09:41:39   作者:qinxun2008081  
單點(diǎn)登錄是一種統(tǒng)一認(rèn)證和授權(quán)機(jī)制,指在多個(gè)應(yīng)用系統(tǒng)中,用戶(hù)只需要登錄一次就可以訪問(wèn)所有相互信任的系統(tǒng),不需要重新登錄驗(yàn)證,這篇文章主要介紹了SpringBoot+JWT實(shí)現(xiàn)單點(diǎn)登錄解決方案,需要的朋友可以參考下

一、什么是單點(diǎn)登錄?

單點(diǎn)登錄是一種統(tǒng)一認(rèn)證和授權(quán)機(jī)制,指在多個(gè)應(yīng)用系統(tǒng)中,用戶(hù)只需要登錄一次就可以訪問(wèn)所有相互信任的系統(tǒng),不需要重新登錄驗(yàn)證。

單點(diǎn)登錄一般用于互相授信的系統(tǒng),實(shí)現(xiàn)單一位置登錄,其他信任的應(yīng)用直接免登錄的方式,在多個(gè)應(yīng)用系統(tǒng)中,只需要登錄一次,就可以訪問(wèn)其他互相信任的應(yīng)用系統(tǒng)。

隨著時(shí)代的演進(jìn),大型web系統(tǒng)早已從單體應(yīng)用架構(gòu)發(fā)展為如今的多系統(tǒng)分布式應(yīng)用群。但無(wú)論系統(tǒng)內(nèi)部多么復(fù)雜,對(duì)用戶(hù)而言,都是一個(gè)統(tǒng)一的整體,訪問(wèn)web系統(tǒng)的整個(gè)應(yīng)用群要和訪問(wèn)單個(gè)系統(tǒng)一樣,登錄/注銷(xiāo)只要一次就夠了,不可能讓一個(gè)用戶(hù)在每個(gè)業(yè)務(wù)系統(tǒng)上都進(jìn)行一次登錄驗(yàn)證操作,這時(shí)就需要獨(dú)立出一個(gè)單獨(dú)的認(rèn)證系統(tǒng),它就是單點(diǎn)登錄系統(tǒng)。

二、單點(diǎn)登錄的優(yōu)點(diǎn)

1.方便用戶(hù)使用。用戶(hù)不需要多次登錄系統(tǒng),不需要記住多個(gè)密碼,方便用戶(hù)操作。

2.提高開(kāi)發(fā)效率。單點(diǎn)登錄為開(kāi)發(fā)人員提供類(lèi)一個(gè)通用的驗(yàn)證框架。

3.簡(jiǎn)化管理。如果在應(yīng)用程序中加入了單點(diǎn)登錄的協(xié)議,管理用戶(hù)賬戶(hù)的負(fù)擔(dān)就會(huì)減輕。

三、JWT 機(jī)制

JWT(JSON Web Token)它將用戶(hù)信息加密到token里,服務(wù)器不保存任何用戶(hù)信息。服務(wù)器通過(guò)使用保存的密鑰驗(yàn)證JWTToken的正確性,只要正確就通過(guò)驗(yàn)證。

數(shù)據(jù)結(jié)構(gòu):

JWT包含三個(gè)部分:Header頭部,Payload負(fù)載和Signature簽名。三個(gè)部門(mén)用“.”分割。校驗(yàn)也是JWT內(nèi)部自己實(shí)現(xiàn)的 ,并且可以將你存儲(chǔ)時(shí)候的信息從token中取出來(lái)無(wú)須查庫(kù)。

JWT執(zhí)行流程:

JWT的請(qǐng)求流程也特別簡(jiǎn)單,首先使用賬號(hào)登錄獲取Token,然后后面的各種請(qǐng)求,都帶上這個(gè)Token即可。具體流程如下:

1. 客戶(hù)端發(fā)起登錄請(qǐng)求,傳入賬號(hào)密碼;

2. 服務(wù)端使用私鑰創(chuàng)建一個(gè)Token;

3. 服務(wù)器返回Token給客戶(hù)端;

4. 客戶(hù)端向服務(wù)端發(fā)送請(qǐng)求,在請(qǐng)求頭中攜帶Token;

5. 服務(wù)器驗(yàn)證該Token;

6. 返回結(jié)果。

四.創(chuàng)建Maven父項(xiàng)目

 2.指定打包類(lèi)型為pom

 五.創(chuàng)建認(rèn)證模塊sso

 1.添加依賴(lài),完整的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sso</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sso</name>
    <description>sso</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.2</version>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2添加jwt相關(guān)配置

 3.創(chuàng)建JWT配置類(lèi)和JWT工具類(lèi)

示例代碼如下:

package com.example.sso.bean;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * @author qx
 * @date 2023/7/4
 * @des Jwt配置類(lèi)
 */
@Component
@ConfigurationProperties(prefix = "jwt")
@Getter
@Setter
public class JwtProperties {
    /**
     * 過(guò)期時(shí)間-分鐘
     */
    private Integer expireTime;
    /**
     * 密鑰
     */
    private String secret;
}
package com.example.sso.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.sso.bean.JwtProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
 * @author qx
 * @date 2023/7/4
 * @des JWT工具類(lèi)
 */
@Component
public class JwtUtil {
    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 生成一個(gè)jwt字符串
     *
     * @param username 用戶(hù)名
     * @return jwt字符串
     */
    public String sign(String username) {
        Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
        return JWT.create()
                // 設(shè)置過(guò)期時(shí)間1個(gè)小時(shí)
                .withExpiresAt(new Date(System.currentTimeMillis() + jwtProperties.getExpireTime() * 60 * 1000))
                // 設(shè)置負(fù)載
                .withClaim("username", username).sign(algorithm);
    }
    public static void main(String[] args) {
        Algorithm algorithm = Algorithm.HMAC256("KU5TjMO6zmh03bU3");
        String username = "admin";
        String token = JWT.create()
                // 設(shè)置過(guò)期時(shí)間1個(gè)小時(shí)
                .withExpiresAt(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                // 設(shè)置負(fù)載
                .withClaim("username", username).sign(algorithm);
        System.out.println(token);
    }
    /**
     * 校驗(yàn)token是否正確
     *
     * @param token token值
     */
    public boolean verify(String token) {
        if (token == null || token.length() == 0) {
            throw new RuntimeException("token為空");
        }
        try {
            Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            jwtVerifier.verify(token);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

4.創(chuàng)建服務(wù)層

package com.example.sso.service;
import com.example.sso.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @author qx
 * @date 2023/7/4
 * @des 登錄服務(wù)層
 */
@Service
public class LoginService {
    @Autowired
    private JwtUtil jwtUtil;
    /**
     * 登錄
     *
     * @param username 用戶(hù)名
     * @param password 密碼
     * @return token值
     */
    public String login(String username, String password) {
        if ("".equals(username) || "".equals(password)) {
            throw new RuntimeException("用戶(hù)名或密碼不能為空");
        }
        // 為了測(cè)試方便 不去數(shù)據(jù)庫(kù)比較密碼
        if ("123".equals(password)) {
            // 返回生成的token
            return jwtUtil.sign(username);
        }
        return null;
    }
    /**
     * 校驗(yàn)jwt是否成功
     *
     * @param token    token值
     * @return 校驗(yàn)是否超過(guò)
     */
    public boolean checkJwt(String token) {
        return jwtUtil.verify(token);
    }
}

5.創(chuàng)建控制層

package com.example.sso.controller;
import com.example.sso.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * @author qx
 * @date 2023/7/4
 * @des 驗(yàn)證控制層
 */
@Controller
@RequestMapping("/sso")
public class AuthController {
    @Autowired
    private LoginService loginService;
    /**
     * 登錄頁(yè)面
     */
    @GetMapping("/login")
    public String toLogin() {
        return "login";
    }
    /**
     * 登錄
     *
     * @param username 用戶(hù)名
     * @param password 密碼
     * @return token值
     */
    @PostMapping("/login")
    @ResponseBody
    public String login(String username, String password) {
        return loginService.login(username, password);
    }
    /**
     * 驗(yàn)證jwt
     *
     * @param token token
     * @return 驗(yàn)證jwt是否合法
     */
    @RequestMapping("/checkJwt")
    @ResponseBody
    public boolean checkJwt(String token) {
        return loginService.checkJwt(token);
    }
}

6.創(chuàng)建一個(gè)登錄頁(yè)面login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
</head>
<body>
    <form method="post" action="/sso/login">
        用戶(hù)名:<input type="text" name="username"/><br/>
        密碼:<input type="password" name="password"/><br/>
        <button type="submit">登錄</button>
    </form>
</body>
</html>

六、創(chuàng)建應(yīng)用系統(tǒng)projectA 

 1.項(xiàng)目pom文件如下所示

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.example</groupId>
        <artifactId>my-sso</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>projectA</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.13</version>
        </dependency>
        <!--okhttp-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
        </dependency>
    </dependencies>
</project>

 2.修改配置文件

 3.創(chuàng)建過(guò)濾器

package com.example.projectA.filter;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @author qx
 * @date 2023/7/4
 * @des 登錄過(guò)濾器
 */
@Component
@WebFilter(urlPatterns = "/**")
public class LoginFilter implements Filter {
    @Value("${sso_server}")
    private String serverHost;
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String token = httpServletRequest.getParameter("token");
        if (this.check(token)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String redirect = serverHost + "/login";
            response.sendRedirect(redirect);
        }
    }
    /**
     * 驗(yàn)證token
     *
     * @param token
     * @return
     * @throws IOException
     */
    private boolean check(String token) throws IOException {
        if (token == null || token.trim().length() == 0) {
            return false;
        }
        OkHttpClient client = new OkHttpClient();
        // 請(qǐng)求驗(yàn)證token的合法性
        String url = serverHost + "/checkJwt?token=" + token;
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        return Boolean.parseBoolean(response.body().string());
    }
}

4.創(chuàng)建測(cè)試控制層

package com.example.projectA.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author qx
 * @date 2023/7/4
 * @des 測(cè)試A
 */
@RestController
public class IndexController {
    @GetMapping("/testA")
    public String testA() {
        return "輸出testA";
    }
}

5.啟動(dòng)類(lèi)

package com.example.projectA;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
 * @author qx
 * @date 2023/7/4
 * @des Projecta啟動(dòng)類(lèi)
 */
@SpringBootApplication
@ServletComponentScan
public class ProjectaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProjectaApplication.class,args);
    }
}

6.啟動(dòng)項(xiàng)目測(cè)試

我們?cè)L問(wèn)http://localhost:8081/testA 系統(tǒng)跳轉(zhuǎn)到了驗(yàn)證模塊的登錄頁(yè)面

我們輸入賬號(hào)密碼登錄成功后返回token

 如何我們復(fù)制這段數(shù)據(jù),把數(shù)據(jù)傳遞到token參數(shù)。

 我們看到正確獲取到了數(shù)據(jù)。

七、創(chuàng)建應(yīng)用系統(tǒng)projectB

我們?cè)俅文7聀rojectA創(chuàng)建projectB子模塊。

 啟動(dòng)模塊B

我們直接測(cè)試帶上token參數(shù)

通過(guò)之前的token,無(wú)需登錄即可成功進(jìn)入了應(yīng)用系統(tǒng)B。說(shuō)明我們的單點(diǎn)登錄系統(tǒng)搭建成功。

到此這篇關(guān)于SpringBoot+JWT實(shí)現(xiàn)單點(diǎn)登錄解決方案的文章就介紹到這了,更多相關(guān)SpringBoot JWT單點(diǎn)登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA實(shí)現(xiàn)利用第三方平臺(tái)發(fā)送短信驗(yàn)證碼

    JAVA實(shí)現(xiàn)利用第三方平臺(tái)發(fā)送短信驗(yàn)證碼

    本文以注冊(cè)為例,在SpringMVC+Spring+Mybatis框架的基礎(chǔ)上完成該短信驗(yàn)證碼功能。需要的朋友一起來(lái)看下吧
    2016-12-12
  • 分享J2EE的13種核心技術(shù)

    分享J2EE的13種核心技術(shù)

    在本文中我將解釋支撐J2EE的13種核心技術(shù):JDBC, JNDI, EJBs, RMI, JSP, Java servlets, XML, JMS, Java IDL, JTS, JTA, JavaMail 和 JAF,對(duì)j2ee的13種核心技術(shù)感興趣的朋友一起學(xué)習(xí)吧
    2015-11-11
  • Java利用Easyexcel導(dǎo)出excel表格的示例代碼

    Java利用Easyexcel導(dǎo)出excel表格的示例代碼

    這篇文章主要為大家詳細(xì)介紹了Java利用Easyexcel導(dǎo)出excel表格的示例代碼,文中的代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2022-07-07
  • Apache Calcite進(jìn)行SQL解析(java代碼實(shí)例)

    Apache Calcite進(jìn)行SQL解析(java代碼實(shí)例)

    Calcite是一款開(kāi)源SQL解析工具, 可以將各種SQL語(yǔ)句解析成抽象語(yǔ)法樹(shù)AST(Abstract Syntax Tree), 之后通過(guò)操作AST就可以把SQL中所要表達(dá)的算法與關(guān)系體現(xiàn)在具體代碼之中,今天通過(guò)代碼實(shí)例給大家介紹Apache Calcite進(jìn)行SQL解析問(wèn)題,感興趣的朋友一起看看吧
    2022-01-01
  • SpringMVC的源碼解析

    SpringMVC的源碼解析

    本文主要介紹了SpringMVC的源碼解析。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解

    java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解

    這篇文章主要為大家介紹了java Disruptor構(gòu)建高性能內(nèi)存隊(duì)列使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • java實(shí)現(xiàn)模擬USB接口的功能

    java實(shí)現(xiàn)模擬USB接口的功能

    本文主要介紹了java實(shí)現(xiàn)模擬USB接口的功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • spring AOP的After增強(qiáng)實(shí)現(xiàn)方法實(shí)例分析

    spring AOP的After增強(qiáng)實(shí)現(xiàn)方法實(shí)例分析

    這篇文章主要介紹了spring AOP的After增強(qiáng)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了spring面向切面AOP的After增強(qiáng)實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2020-01-01
  • java根據(jù)方法名稱(chēng)取得反射方法的參數(shù)類(lèi)型示例

    java根據(jù)方法名稱(chēng)取得反射方法的參數(shù)類(lèi)型示例

    利用java反射原理調(diào)用方法時(shí),常先需要傳入方法參數(shù)數(shù)組才能取得方法。該方法參數(shù)數(shù)組采用動(dòng)態(tài)取得的方式比較合適
    2014-02-02
  • SpringBoot2 JPA解決懶加載異常的問(wèn)題

    SpringBoot2 JPA解決懶加載異常的問(wèn)題

    這篇文章主要介紹了SpringBoot2 JPA解決懶加載異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01

最新評(píng)論