溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

發(fā)布時(shí)間:2020-07-01 16:00:14 來(lái)源:億速云 閱讀:871 作者:清晨 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

  一、基于JWT實(shí)現(xiàn)SSO單點(diǎn)登錄原理

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

  所謂單點(diǎn)登錄就是有多個(gè)應(yīng)用部署在不同的服務(wù)器上,只需登錄一次就可以互相訪(fǎng)問(wèn)不同服務(wù)器上的資源。

  2、單點(diǎn)登錄流程

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  當(dāng)一個(gè)訪(fǎng)問(wèn)請(qǐng)求發(fā)給應(yīng)用A,如果這個(gè)請(qǐng)求需要登錄以后才能訪(fǎng)問(wèn),那么應(yīng)用A就會(huì)向認(rèn)證服務(wù)器請(qǐng)求授權(quán),這時(shí)候就把用戶(hù)引導(dǎo)到認(rèn)證服務(wù)器上。用戶(hù)在認(rèn)證服務(wù)器上完成認(rèn)證并授權(quán)。認(rèn)證授權(quán)完成后,認(rèn)證服務(wù)器返回給應(yīng)用A一個(gè)授權(quán)碼,應(yīng)用A攜帶授權(quán)碼到認(rèn)證服務(wù)器請(qǐng)求令牌,認(rèn)證服務(wù)器返回應(yīng)用A一個(gè)JWT,應(yīng)用A解析JWT里面的信息,完成登錄。這是一個(gè)標(biāo)準(zhǔn)的OAuth3的授權(quán)碼流程。

  走完認(rèn)證流程后,給出去的JWT實(shí)際上里面包含的就是當(dāng)前用戶(hù)在認(rèn)證服務(wù)器上登錄以后用戶(hù)的認(rèn)證信息,應(yīng)用A解析JWT后,自己生成一個(gè)經(jīng)過(guò)認(rèn)證的Authentication放到它的SpringSecurity和SecurityContext里面。

  當(dāng)訪(fǎng)問(wèn)應(yīng)用服務(wù)器B的時(shí)候,同樣引導(dǎo)用戶(hù)去認(rèn)證服務(wù)器請(qǐng)求授權(quán)(不需要登錄),用戶(hù)授權(quán)可以用登錄的信息去訪(fǎng)問(wèn)應(yīng)用B,后面同樣是授權(quán)碼流程,返回JWT給應(yīng)用B。兩個(gè)應(yīng)用返回不同的JWT,但是解析出的信息是一樣的。

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

  1、父工程(sso-demo)

  1)pom.xml

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.0.4.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security.oauth.boot</groupId>
      <artifactId>spring-security-oauth3-autoconfigure</artifactId>
      <version>2.1.3.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-jwt</artifactId>
      <version>1.0.10.RELEASE</version>
    </dependency>
  </dependencies>
</dependencyManagement>

  2、認(rèn)證服務(wù)(sso-server)

  1)pom.xml

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth3-autoconfigure</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-jwt</artifactId>
</dependency>

  2)application.properties

server.port = 9999
server.servlet.context-path = /server

  3)WebSecurityConfig.java

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().and().csrf().disable();   
  }
  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
}

  4)MyUserDetailsService.java

@Component
public class MyUserDetailsService implements UserDetailsService{

  @Autowired
  private PasswordEncoder passwordEncoder;
  
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    System.out.println("登錄用戶(hù)名:"+username);
    String password = passwordEncoder.encode("123456");
    return new User(username,password,true,true,true,true,
        AuthorityUtils.commaSeparatedStringToAuthorityList("all"));
  }
}

  5)SsoAuthorizationServerConfig.java

@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  
  @Autowired
  private PasswordEncoder passwordEncoder;
  
  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
        .withClient("appclient_1").secret(passwordEncoder.encode("client1_123456"))
        .authorizedGrantTypes("authorization_code","refresh_token")
        .scopes("all")
        .redirectUris("http://127.0.0.1:8080/client1/login")
       .and()
        .withClient("appclient_2").secret(passwordEncoder.encode("client2_123456"))
        .authorizedGrantTypes("authorization_code","refresh_token")
        .scopes("all")
        .redirectUris("http://127.0.0.1:8060/client2/login");
  }
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter());
  }
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.tokenKeyAccess("isAuthenticated()");//訪(fǎng)問(wèn)tokenKey(秘鑰shxiang)的時(shí)候需要身份認(rèn)證 
  }
  @Bean
  public TokenStore jwtTokenStore() {
    return new JwtTokenStore(jwtAccessTokenConverter());
  }
  @Bean
  public JwtAccessTokenConverter jwtAccessTokenConverter() {
    JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
    accessTokenConverter.setSigningKey("shxiang");//設(shè)置秘鑰
    return accessTokenConverter;
  }
}

  6)SsoServerApplication.java

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

  3、應(yīng)用1(sso-client1)

  1)pom.xml,同上

  2)application.properties

security.oauth3.client.client-id = appclient_1
security.oauth3.client.client-secret = client1_123456
security.oauth3.client.user-authorization-uri = http://127.0.0.1:9999/server/oauth/authorize

security.oauth3.client.access-token-uri = http://127.0.0.1:9999/server/oauth/token
security.oauth3.resource.jwt.key-uri = http://127.0.0.1:9999/server/oauth/token_key

server.port=8080
server.servlet.context-path =/client1

  3)index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SSO Client1</title>
</head>
<body>
  <h2>SSO Demo Client1</h2>
  <a href="http://127.0.0.1:8060/client2/index.html" rel="external nofollow" >訪(fǎng)問(wèn)Client2</a>
</body>
</html>

  4)SsoClient1Application.java

@SpringBootApplication
@RestController
@EnableOAuth3Sso
public class SsoClient1Application {
  public static void main(String[] args) {
    SpringApplication.run(SsoClient1Application.class, args);
  }
  @GetMapping("/user")
  public Authentication user(Authentication user) {
    return user;
  }
}

  4、應(yīng)用2(sso-client2)

  1)pom.xml,同上

  2)application.properties,類(lèi)比應(yīng)用1修改

  3)index.html,類(lèi)比應(yīng)用1修改

  4)SsoClient2Application.java,同上

  5、測(cè)試

  1)瀏覽器輸入:127.0.0.1:8080/client1/index.html

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  2)用戶(hù)名隨便輸入,密碼輸入123456

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  3)點(diǎn)擊Authorize 

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  4)點(diǎn)擊超級(jí)鏈接訪(fǎng)問(wèn)Client2

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  5)點(diǎn)擊Authorize

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  認(rèn)證成功,后面點(diǎn)擊兩個(gè)超級(jí)鏈接可以任意訪(fǎng)問(wèn),無(wú)需登錄 、無(wú)需點(diǎn)擊Authorize。

  注意:

  1)雖是同一用戶(hù),但是訪(fǎng)問(wèn)http://127.0.0.1:8080/client1/user和http://127.0.0.1:8060/client2/user獲取的Token值不一樣。

  2)實(shí)現(xiàn)跳過(guò)授權(quán),登錄后直接訪(fǎng)問(wèn),修改如下代碼:

JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟

  3)表單登錄與httpBasic登錄,修改WebSecurityConfig.java中configure方法

httpBasic登錄:http.httpBasic().and().csrf().disable();
表單登錄:http.formLogin().and().authorizeRequests().anyRequest().authenticated();

  4)重點(diǎn):瀏覽器訪(fǎng)問(wèn)要用127.0.0.1不要用localhost。要設(shè)置應(yīng)用路徑server.servlet.context-path =/xxxx,不能直接到端口號(hào)。

以上是JWT實(shí)現(xiàn)SSO單點(diǎn)登錄的流程步驟的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI