打开websocket连接的升级请求是标准HTTP请求。在服务器端,我可以像其他任何一样对请求进行身份验证。就我而言,我想使用Bearer身份验证。不幸的是,在浏览器中打开websocket连接时无法指定标题,这会让我相信使用承载身份验证来验证Web套接字升级请求是不可能的。所以 - 我错过了什么,还是真的不可能?如果不可能,这是设计,还是在websocket API的浏览器实现中明显疏忽?
答案 0 :(得分:21)
API允许您准确设置一个标头,即 Sec-WebSocket-Protocol ,即特定于应用程序的子协议。您可以使用此标头传递持有者令牌。例如:
new WebSocket("ws://www.example.com/socketserver", ["access_token", "3gn11Ft0Me8lkqqW2/5uFQ="]);
服务器应该接受其中一个协议,因此对于上面的示例,您只需验证令牌并使用标头 Sec-WebSocket-Protocol = access_token 进行响应。
答案 1 :(得分:9)
你是对的,由于Javascript WebSocket API的设计,现在不可能使用Authentication头。 可在此主题中找到更多信息: HTTP headers in Websockets client API
但是,Bearer身份验证类型允许名为" access_token":http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html#query-param的请求参数 此方法与websocket连接兼容。
答案 2 :(得分:-1)
在网络套接字连接之前使用令牌servlet http请求标头进行基本身份验证的示例:
**** ws:// localhost:8081 / remoteservice / id?access_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>
根据需要在js文件中添加请求标头
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)