天天看點

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入

作者:Java程式設計世界

二維碼掃碼登入已經成為了現代網際網路時代的一種普遍的登入方式。它的出現,極大地友善了使用者登入的流程,減少了使用者輸入使用者名和密碼的麻煩。在二維碼掃碼登入流程中,使用者隻需要通過掃描二維碼的方式即可完成登入,免去了許多繁瑣的操作。而在這篇文章中,我将為大家介紹二維碼掃碼登入的原理,并提供一種使用SpringBoot架構實作該功能的具體方法。

一、二維碼掃碼登入的原理

二維碼掃碼登入是一種基于OAuth2.0協定的授權登入方式。在這種方式下,應用程式不需要擷取使用者的使用者名和密碼,隻需要擷取使用者的授權即可。二維碼掃碼登入主要有以下幾個步驟:

  1. 應用程式生成一個二維碼,并将該二維碼展示給使用者。
  2. 使用者使用掃碼工具掃描該二維碼,并在授權頁面中授權。
  3. 使用者授權後,應用程式會擷取一個授權碼。
  4. 應用程式使用該授權碼向授權伺服器請求通路令牌。
  5. 授權伺服器傳回一個通路令牌給應用程式。
  6. 應用程式使用該通路令牌通路資源伺服器。
掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入

通過以上步驟,二維碼掃碼登入可以實作使用者的快速登入,并保證了使用者的安全性和隐私性。

二、SpringBoot如何實作二維碼掃碼登入

在SpringBoot中,可以使用Spring Security OAuth2.0來實作二維碼掃碼登入功能。Spring Security OAuth2.0是一個基于OAuth2.0協定的安全架構,它提供了授權伺服器和資源伺服器的實作。下面,我将為大家介紹如何使用Spring Security OAuth2.0實作二維碼掃碼登入。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入
  1. 添加依賴

首先,需要在pom.xml檔案中添加Spring Security OAuth2.0的依賴:

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.4.0</version>
</dependency>
           
  1. 配置授權伺服器

在SpringBoot中,可以通過@Configuration注解來配置授權伺服器。下面是一個簡單的授權伺服器配置示例:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret("{noop}secret")
                .authorizedGrantTypes("authorization_code")
                .scopes("read", "write")
                .redirectUris("http://localhost:8080/callback");
    }

    @Override
    public void configure(AuthorizationServerEndpoints endpoints) throws Exception {
    endpoints.authenticationManager(authenticationManager);
}
}           

在上面的代碼中,使用@EnableAuthorizationServer注解來啟用授權伺服器。然後,通過@Configuration注解來指定該類為一個配置類。在configure()方法中,配置了一個授權用戶端,并指定了授權類型為authorization_code。授權伺服器通過inMemory()方法來指定用戶端的資訊,包括用戶端ID、用戶端秘鑰、授權類型、授權範圍以及重定向位址等資訊。在configure()方法中,還需要配置AuthenticationManager,用于驗證使用者的身份資訊。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入

3. 配置資源伺服器

在SpringBoot中,可以通過@Configuration注解來配置資源伺服器。下面是一個簡單的資源伺服器配置示例:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  @Override
public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/api/**").authenticated()
            .anyRequest().permitAll();
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("resource");
}
}           

在上面的代碼中,使用@EnableResourceServer注解來啟用資源伺服器。然後,通過@Configuration注解來指定該類為一個配置類。在configure()方法中,配置了資源伺服器的安全政策,使用antMatchers()方法指定了需要認證的接口,使用permitAll()方法指定了其他接口可以被匿名通路。在configure()方法中,還需要配置資源伺服器的資源ID。

4. 配置用戶端

在SpringBoot中,可以通過配置檔案來配置用戶端。下面是一個簡單的用戶端配置示例:

security:
oauth2:
client:
clientId: client
clientSecret: secret
accessTokenUri: http://localhost:8080/oauth/token
userAuthorizationUri: http://localhost:8080/oauth/authorize
scope: read,write
redirectUri: http://localhost:8080/callback           

在上面的代碼中,通過security.oauth2.client字首來指定用戶端的配置資訊,包括用戶端ID、用戶端秘鑰、通路令牌URI、使用者授權URI、授權範圍、重定向位址等資訊。

5. 生成二維碼

在SpringBoot中,可以使用第三方庫來生成二維碼。下面是一個簡單的二維碼生成示例:

@GetMapping("/qrcode")
public ResponseEntity<byte[]> getQRCode() throws IOException, WriterException {
String codeUrl = "http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://localhost:8080/callback";
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl, BarcodeFormat.QR_CODE, 200, 200);
MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);
return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(outputStream.toByteArray());
}           

在上面的代碼中,使用@GetMapping注解來指定該方法為一個GET請求處理方法,通過指定請求路徑"/qrcode"來映射該方法。在getQRCode()方法中,首先生成授權請求的URL,并使用第三方庫生成二維碼圖檔。最後,将生成的二維碼圖檔以byte數組的形式傳回給用戶端。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入
  1. 掃碼登入

在SpringBoot中,可以使用WebSocket來實作掃碼登入功能。下面是一個簡單的掃碼登入示例:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new QRCodeHandler(), "/qrcodeHandler");
    }

    class QRCodeHandler extends TextWebSocketHandler {

        private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

        @Override
        public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            String token = message.getPayload();
            if (sessions.containsKey(token)) {
                WebSocketSession clientSession = sessions.get(token);
                clientSession.sendMessage(new TextMessage("authenticated"));
                session.sendMessage(new TextMessage("authenticated"));
            } else {
                sessions.put(token, session);
            }
        }

        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
            sessions.values().remove(session);
        }
    }
}
           

在上面的代碼中,使用@EnableWebSocket注解來啟用WebSocket支援。然後,通過@Configuration注解來指定該類為一個配置類。在registerWebSocketHandlers()方法中,注冊了一個WebSocket處理器,并指定了處理器的請求路徑。在QRCodeHandler類中,實作了WebSocket處理器的業務邏輯。在handleTextMessage()方法中,将二維碼掃描後生成的token作為key,将WebSocket會話對象儲存在Map中。如果同一個token對應的WebSocket會話對象已存在,則表示該使用者已經掃碼并且已經認證通過,此時需要将兩個WebSocket會話對象互相通知認證通過。如果同一個token對應的WebSocket會話對象不存在,則将該WebSocket會話對象儲存在Map中。在afterConnectionClosed()方法中,移除已關閉的WebSocket會話對象。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入
  1. 用戶端回調

在SpringBoot中,可以使用@Controller注解來實作用戶端的回調功能。下面是一個簡單的回調示例:

@Controller
public class CallbackController {

    @Autowired
    private OAuth2RestTemplate restTemplate;

    @GetMapping("/callback")
    public String callback(@RequestParam("code") String code) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("code", code);
        params.add("redirect_uri", "http://localhost:8080/callback");
        params.add("client_id", "client");
        params.add("client_secret", "secret");
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
        OAuth2AccessToken token = restTemplate.postForObject("http://localhost:8080/oauth/token", request, OAuth2AccessToken.class);
        return "redirect:/home";
    }
}
           

在上面的代碼中,使用@Controller注解來指定該類為一個控制器。在callback()方法中,首先使用OAuth2RestTemplate來發送POST請求擷取通路令牌,并将授權碼、回調URL、用戶端ID和用戶端秘鑰等參數作為請求體發送。在擷取到通路令牌之後,重定向到應用程式的首頁。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入

三、總結

二維碼掃碼登入是一種友善快捷的身份認證方式,可以為使用者提供更好的登入體驗。在SpringBoot中,可以使用QRCodeGenerator類生成二維碼圖檔,使用WebSocket實作掃碼登入功能,使用OAuth2RestTemplate實作用戶端回調功能。通過以上的介紹,相信讀者已經對二維碼掃碼登入的原理及SpringBoot的實作方式有了一定的了解。

掏出手機,掃一掃,即刻登入——SpringBoot實作二維碼掃碼登入