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

Spring中Websocket身份驗(yàn)證和授權(quán)的實(shí)現(xiàn)

 更新時間:2023年08月18日 10:23:58   作者:timi先生  
在Web應(yīng)用開發(fā)中,安全一直是非常重要的一個方面,本文主要介紹了Spring中Websocket身份驗(yàn)證和授權(quán)的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下

一、需要了解的事項(xiàng)

  • http和WebSocket的安全鏈和安全配置是完全獨(dú)立的。
  • SpringAuthenticationProvider根本不參與 Websocket 身份驗(yàn)證。
  • 將要給出的示例中,身份驗(yàn)證不會發(fā)生在 HTTP 協(xié)商端點(diǎn)上,因?yàn)?JavaScript STOMP(websocket)庫不會隨 HTTP 請求一起發(fā)送必要的身份驗(yàn)證標(biāo)頭。
  • 一旦在 CONNECT 請求上設(shè)置,用戶( simpUser) 將被存儲在 websocket 會話中,并且以后的消息將不再需要進(jìn)行身份驗(yàn)證。

二、依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-messaging</artifactId>
</dependency>

三、WebSocket 配置

3.1 、簡單的消息代理

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(final MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue/topic");
        config.setApplicationDestinationPrefixes("/app");
    }
    @Override
    public void registerStompEndpoints(final StompEndpointRegistry registry) {
        registry.addEndpoint("stomp"); 
        setAllowedOrigins("*")
    }
}

3.2 、Spring安全配置

由于 Stomp 協(xié)議依賴于第一個 HTTP 請求,因此需要授權(quán)對 stomp 握手端點(diǎn)的 HTTP 調(diào)用。

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(final HttpSecurity http) throws Exception
        http.httpBasic().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers("/stomp").permitAll()
                .anyRequest().denyAll();
    }
}

然后創(chuàng)建一個負(fù)責(zé)驗(yàn)證用戶身份的服務(wù)。

@Component
public class WebSocketAuthenticatorService {
    public UsernamePasswordAuthenticationToken getAuthenticatedOrFail(final String  username, final String password) throws AuthenticationException {
        if (username == null || username.trim().isEmpty()) {
            throw new AuthenticationCredentialsNotFoundException("Username was null or empty.");
        }
        if (password == null || password.trim().isEmpty()) {
            throw new AuthenticationCredentialsNotFoundException("Password was null or empty.");
        }
        if (fetchUserFromDb(username, password) == null) {
            throw new BadCredentialsException("Bad credentials for user " + username);
        }
        return new UsernamePasswordAuthenticationToken(
                username,
                null,
                Collections.singleton((GrantedAuthority) () -> "USER") // 必須給至少一個角色
        );
    }
}

接著需要創(chuàng)建一個攔截器,它將設(shè)置“simpUser”標(biāo)頭或在 CONNECT 消息上拋出“AuthenticationException”。

@Component
public class AuthChannelInterceptorAdapter extends ChannelInterceptor {
    private static final String USERNAME_HEADER = "login";
    private static final String PASSWORD_HEADER = "passcode";
    private final WebSocketAuthenticatorService webSocketAuthenticatorService;
    @Inject
    public AuthChannelInterceptorAdapter(final WebSocketAuthenticatorService webSocketAuthenticatorService) {
        this.webSocketAuthenticatorService = webSocketAuthenticatorService;
    }
    @Override
    public Message<?> preSend(final Message<?> message, final MessageChannel channel) throws AuthenticationException {
        final StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT == accessor.getCommand()) {
            final String username = accessor.getFirstNativeHeader(USERNAME_HEADER);
            final String password = accessor.getFirstNativeHeader(PASSWORD_HEADER);
            final UsernamePasswordAuthenticationToken user = webSocketAuthenticatorService.getAuthenticatedOrFail(username, password);
            accessor.setUser(user);
        }
        return message;
    }
}

請注意:preSend() 必須返回 UsernamePasswordAuthenticationToken,Spring 安全鏈中會對此進(jìn)行測試。如果UsernamePasswordAuthenticationToken構(gòu)建沒有通過GrantedAuthority,則身份驗(yàn)證將失敗,因?yàn)闆]有授予權(quán)限的構(gòu)造函數(shù)自動設(shè)置authenticated = false 這是一個重要的細(xì)節(jié),在 spring-security 中沒有記錄。

最后再創(chuàng)建兩個類來分別處理授權(quán)和身份驗(yàn)證。

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationSecurityConfig extends  WebSocketMessageBrokerConfigurer {
    @Inject
    private AuthChannelInterceptorAdapter authChannelInterceptorAdapter;
    @Override
    public void registerStompEndpoints(final StompEndpointRegistry registry) {
        // 這里不用給任何東西
    }
    @Override
    public void configureClientInboundChannel(final ChannelRegistration registration) {
        registration.setInterceptors(authChannelInterceptorAdapter);
    }
}

請注意:這@Order是至關(guān)重要的,它允許我們的攔截器首先在安全鏈中注冊。

@Configuration
public class WebSocketAuthorizationSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
    @Override
    protected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) {
        // 添加自己的映射
        messages.anyMessage().authenticated();
    }
    // 這里請自己按需求修改
    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }
}

之后編寫客戶端進(jìn)行連接,我們就可以這樣指定客戶端進(jìn)行消息的發(fā)送。

    @MessageMapping("/greeting")
    public void greetingReturn(@Payload Object ojd){
         simpMessagingTemplate.convertAndSendToUser(username,"/topic/greeting",ojd);
    }

到此這篇關(guān)于Spring中Websocket身份驗(yàn)證和授權(quán)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Spring Websocket身份驗(yàn)證和授權(quán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot+Shiro+Mybatis+mysql實(shí)現(xiàn)權(quán)限安全認(rèn)證的示例代碼

    Springboot+Shiro+Mybatis+mysql實(shí)現(xiàn)權(quán)限安全認(rèn)證的示例代碼

    Shiro是Apache?的一個強(qiáng)大且易用的Java安全框架,執(zhí)行身份驗(yàn)證、授權(quán)、密碼學(xué)和會話管理,Shiro?主要分為兩個部分就是認(rèn)證和授權(quán)兩部分,這篇文章主要介紹了Springboot+Shiro+Mybatis+mysql實(shí)現(xiàn)權(quán)限安全認(rèn)證的示例代碼,需要的朋友可以參考下
    2024-07-07
  • SpringBoot項(xiàng)目的漏洞修復(fù)經(jīng)驗(yàn)分享

    SpringBoot項(xiàng)目的漏洞修復(fù)經(jīng)驗(yàn)分享

    在局域網(wǎng)環(huán)境下,由于無法連接外網(wǎng)下載Maven包,常見解決方案是在外網(wǎng)環(huán)境搭建相同的開發(fā)環(huán)境以便更新Maven包,本次漏洞掃描包括Tomcat、jackson-databind、fastjson、logback等組件,通常解決方法是升級到更高版本
    2024-10-10
  • java算法題解LeetCode30包含min函數(shù)的棧實(shí)例

    java算法題解LeetCode30包含min函數(shù)的棧實(shí)例

    這篇文章主要為大家介紹了java算法題解LeetCode30包含min函數(shù)的棧實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法

    Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法

    這篇文章主要介紹了Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-10-10
  • java 實(shí)現(xiàn)圖片合成,并添加文字

    java 實(shí)現(xiàn)圖片合成,并添加文字

    這篇文章主要介紹了java 實(shí)現(xiàn)圖片合成,并添加文字的示例,幫助大家更好的利用Java處理圖片,感興趣的朋友可以了解下
    2020-12-12
  • Spring Cloud工程搭建過程詳解

    Spring Cloud工程搭建過程詳解

    文章介紹了如何使用父子工程搭建SpringCloud項(xiàng)目,包括創(chuàng)建父工程和子項(xiàng)目,以及管理依賴版本,感興趣的朋友一起看看吧
    2025-02-02
  • Java基礎(chǔ)學(xué)習(xí)之Swing事件監(jiān)聽

    Java基礎(chǔ)學(xué)習(xí)之Swing事件監(jiān)聽

    今天學(xué)習(xí)java的Swing庫,創(chuàng)建桌面應(yīng)用的時候,突然發(fā)現(xiàn)有些按鈕需要特定的功能響應(yīng),故來研究一番Swing的事件監(jiān)聽,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-05-05
  • java實(shí)現(xiàn)學(xué)生成績錄入系統(tǒng)

    java實(shí)現(xiàn)學(xué)生成績錄入系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生成績錄入系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Maven中plugins與pluginManagement的區(qū)別說明

    Maven中plugins與pluginManagement的區(qū)別說明

    這篇文章主要介紹了Maven中plugins與pluginManagement的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java固定大小隊列的幾種實(shí)現(xiàn)方式詳解

    java固定大小隊列的幾種實(shí)現(xiàn)方式詳解

    隊列的特點(diǎn)是節(jié)點(diǎn)的排隊次序和出隊次序按入隊時間先后確定,即先入隊者先出隊,后入隊者后出隊,這篇文章主要給大家介紹了關(guān)于java固定大小隊列的幾種實(shí)現(xiàn)方式,需要的朋友可以參考下
    2021-07-07

最新評論