Authentication 是否可以对websocket升级请求使用承载身份验证?

Authentication 是否可以对websocket升级请求使用承载身份验证?,authentication,websocket,authorization,Authentication,Websocket,Authorization,打开websocket连接的升级请求是标准HTTP请求。在服务器端,我可以像其他任何请求一样对请求进行身份验证。在我的情况下,我想使用承载身份验证。不幸的是,在浏览器中打开websocket连接时,无法指定头,这使我相信不可能使用承载身份验证来验证web套接字升级请求。那么,我是错过了什么,还是真的不可能?如果这是不可能的,这是出于设计,还是在websocket API的浏览器实现中存在明显的疏忽?您是对的,由于Javascript websocket API的设计,现在不可能使用身份验证头。

打开websocket连接的升级请求是标准HTTP请求。在服务器端,我可以像其他任何请求一样对请求进行身份验证。在我的情况下,我想使用承载身份验证。不幸的是,在浏览器中打开websocket连接时,无法指定头,这使我相信不可能使用承载身份验证来验证web套接字升级请求。那么,我是错过了什么,还是真的不可能?如果这是不可能的,这是出于设计,还是在websocket API的浏览器实现中存在明显的疏忽?

您是对的,由于Javascript websocket API的设计,现在不可能使用身份验证头。 更多信息可在此线程中找到:

但是,承载身份验证类型允许名为“access_token”的请求参数:
此方法与websocket连接兼容。

API允许您只设置一个标题,即Sec websocket协议,即特定于应用程序的子目录。您可以使用此标头传递承载令牌。例如:

new WebSocket("ws://www.example.com/socketserver", ["access_token", "3gn11Ft0Me8lkqqW2/5uFQ="]);

服务器预期会接受其中一个协议,因此对于上面的示例,您只需验证令牌并使用头Sec WebSocket Protocol=access\u token进行响应。

在WebSocket连接之前使用令牌servlet http请求头进行基本身份验证的示例:

****ws://localhost:8081/remoteservice/id?access\u token=tokenValue****

验证您的令牌返回true(如果有效),否则返回false

端点配置:

@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer{

    @Autowired
    RemoteServiceHandler rsHandler;

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry){
        registry.addHandler(rsHandler, "/remoteservice/{vin}").setAllowedOrigins("*").addInterceptors(new HttpHandshakeInterceptor());
    }   
}
在建立websocket连接之前验证令牌:

public class HttpHandshakeInterceptor implements HandshakeInterceptor{

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,  Map attributes) throws Exception 
{
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
String token = servletRequest.getServletRequest().getHeader("access_token");
try {
            Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();

            if (claims!=null) {
                return true;
            }
        } catch (Exception e) {

            return false;
        }
        return false;
}
跳过http安全端点

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Override 
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().anyRequest(); 
    }

}
pom.xml

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

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

我使用了这种方法,只是我将令牌和值连接在一个“协议”值中。谢谢你有没有一个解决方案使用
授权
Sec WebSocket协议头的头实例?没有,但如果客户端是JS(是的,相当愚蠢),服务器可能更容易读取访问令牌作为承载令牌。我想这取决于你的观点,这是一个功能还是一个黑客,但这意味着它是一个特定于应用程序的子程序,因此应用程序可以随意请求和使用头文件。是的,这仍然是最好的方法。鉴于这在规范中,它不会很快改变,而且我不知道有任何标准化工作允许从js对websocket请求头进行常规访问。另外,要回复@jayong,可以设置cookie,cookie随ws-upgrade请求一起发送。文档告诉您它不安全,除非绝对必要,否则不要使用它。
var request = URLRequest(url: URL(string: "ws://localhost:8081/remoteservice")!)
request.timeoutInterval = 5 // Sets the timeout for the connection
request.setValue("someother protocols", forHTTPHeaderField: "Sec-WebSocket-Protocol")
request.setValue("14", forHTTPHeaderField: "Sec-WebSocket-Version")
request.setValue("chat,superchat", forHTTPHeaderField: "Sec-WebSocket-Protocol")
request.setValue("Everything is Awesome!", forHTTPHeaderField: "My-Awesome-Header")
let socket = WebSocket(request: request)