欧美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)中,用戶只需要登錄一次就可以訪問所有相互信任的系統(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)中,用戶只需要登錄一次就可以訪問所有相互信任的系統(tǒng),不需要重新登錄驗(yàn)證。

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

隨著時(shí)代的演進(jìn),大型web系統(tǒng)早已從單體應(yīng)用架構(gòu)發(fā)展為如今的多系統(tǒng)分布式應(yīng)用群。但無論系統(tǒng)內(nèi)部多么復(fù)雜,對用戶而言,都是一個(gè)統(tǒng)一的整體,訪問web系統(tǒng)的整個(gè)應(yīng)用群要和訪問單個(gè)系統(tǒng)一樣,登錄/注銷只要一次就夠了,不可能讓一個(gè)用戶在每個(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.方便用戶使用。用戶不需要多次登錄系統(tǒng),不需要記住多個(gè)密碼,方便用戶操作。

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

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

三、JWT 機(jī)制

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

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

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

JWT執(zhí)行流程:

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

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

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

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

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

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

6. 返回結(jié)果。

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

 2.指定打包類型為pom

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

 1.添加依賴,完整的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配置類和JWT工具類

示例代碼如下:

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配置類
 */
@Component
@ConfigurationProperties(prefix = "jwt")
@Getter
@Setter
public class JwtProperties {
    /**
     * 過期時(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工具類
 */
@Component
public class JwtUtil {
    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 生成一個(gè)jwt字符串
     *
     * @param username 用戶名
     * @return jwt字符串
     */
    public String sign(String username) {
        Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
        return JWT.create()
                // 設(shè)置過期時(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è)置過期時(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 用戶名
     * @param password 密碼
     * @return token值
     */
    public String login(String username, String password) {
        if ("".equals(username) || "".equals(password)) {
            throw new RuntimeException("用戶名或密碼不能為空");
        }
        // 為了測試方便 不去數(shù)據(jù)庫比較密碼
        if ("123".equals(password)) {
            // 返回生成的token
            return jwtUtil.sign(username);
        }
        return null;
    }
    /**
     * 校驗(yàn)jwt是否成功
     *
     * @param token    token值
     * @return 校驗(yàn)是否超過
     */
    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;
    /**
     * 登錄頁面
     */
    @GetMapping("/login")
    public String toLogin() {
        return "login";
    }
    /**
     * 登錄
     *
     * @param username 用戶名
     * @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è)登錄頁面login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
</head>
<body>
    <form method="post" action="/sso/login">
        用戶名:<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)建過濾器

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 登錄過濾器
 */
@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();
        // 請求驗(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)建測試控制層

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 測試A
 */
@RestController
public class IndexController {
    @GetMapping("/testA")
    public String testA() {
        return "輸出testA";
    }
}

5.啟動(dòng)類

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)類
 */
@SpringBootApplication
@ServletComponentScan
public class ProjectaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProjectaApplication.class,args);
    }
}

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

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

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

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

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

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

我們再次模仿projectA創(chuàng)建projectB子模塊。

 啟動(dòng)模塊B

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

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

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

相關(guān)文章

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

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

    本文以注冊為例,在SpringMVC+Spring+Mybatis框架的基礎(chǔ)上完成該短信驗(yàn)證碼功能。需要的朋友一起來看下吧
    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,對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是一款開源SQL解析工具, 可以將各種SQL語句解析成抽象語法樹AST(Abstract Syntax Tree), 之后通過操作AST就可以把SQL中所要表達(dá)的算法與關(guān)系體現(xiàn)在具體代碼之中,今天通過代碼實(shí)例給大家介紹Apache Calcite進(jìn)行SQL解析問題,感興趣的朋友一起看看吧
    2022-01-01
  • SpringMVC的源碼解析

    SpringMVC的源碼解析

    本文主要介紹了SpringMVC的源碼解析。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    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接口的功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(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ù)方法名稱取得反射方法的參數(shù)類型示例

    java根據(jù)方法名稱取得反射方法的參數(shù)類型示例

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

    SpringBoot2 JPA解決懶加載異常的問題

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

最新評論