Spring 安全 + Angular 2 + SockJS
Spring Security + Angular 2 + SockJS
对不起,一开始我的语言不好。我是一名来自德国的学生,刚开始编程。
我已经使用 Spring Boot 实现了一个小型 websocket 服务器,并使用 Basic Auth 通过 Spring Security 对其进行了保护。 Angular 2 用于前端。我已经实现了以下解决方案来连接到 websocket。
* Connects to a websocket server.
* @param {string} url The url of the WS Server
* @param {string} channel The channel to subscribe
* @return {boolean} connection status
*/
public connect(url: string, channel: string): boolean {
console.group('WebSocketService: Welcome to the connect function.');
console.log('Connects to', url);
console.log('Channel is', channel);
let _self = this;
let socket = new SockJS(url);
_self.wsClient = Stomp.over(socket);
_self.wsClient.connect({}, function(frame) {
_self.setConnected(true);
console.log('Connected: ', frame);
_self.wsClient.subscribe(channel, function(greeting) {
console.log(greeting);
_self.subjects[channel].next(greeting);
});
});
console.groupEnd();
return true;
}
调用此函数让浏览器打开用户名和密码输入。
现在我可以连接和断开与服务器的连接,无需再次输入用户名/密码。
如何使用代码中的登录信息替换此浏览器输入 window?
我试图通过一个 Post 请求来做到这一点,例如:
private test2(){
let username : string = 'admin';
let password : string = 'pass';
let headers = new Headers();
headers.append("Authorization", "Basic " + btoa(username + ":" + password));
headers.append("Content-Type", "application/x-www-form-urlencoded");
console.log('Test beginnt');
return this._http.get('http://localhost:8080/gs-guide-websocket', {headers: headers}).map(res=> console.log(res))
}
Blockquote
但这只给我一个 http 200 响应,并没有打开会话或其他东西。
我也试过将登录信息放在原始请求中。
_self.wsClient.connect('admin','pass', function(frame) { ...}
感谢您的帮助。
我没有使用过 SockJS。但是我已经为纯 WebSocket 实现了一些小机制。也许会有帮助
首先,OAUTH配置:
@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
private static Logger logger = LoggerFactory.getLogger(OAuth2Configuration.class);
private UsersService service = new UsersService();
@Autowired
AuthenticationManagerBuilder authenticationManager;
@Autowired
UserDetailsService userDetailsService;
@Override
public void configure( AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
authenticationManager.userDetailsService(this.userDetailsService);
endpoints.authenticationManager((Authentication authentication) -> authenticationManager.getOrBuild().authenticate(authentication));
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("application_name")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("write", "read", "trust")
.secret("secret").accessTokenValiditySeconds(24 * 60 * 60);
}
@Bean
public UserDetailsService userDetailsService() {
return (username) -> {
return service.getByName(username).map(account -> new User(account.getName(), account.getPassword(), account.getAuthorities())).orElseThrow(
() -> new RuntimeException("User not found")
);
};
}
}
第二,angular2授权:
let headers = new Headers();
headers.append("Authorization", "Basic appname:secret");
this.http.post("localhost:8080/oauth_endpoint?grant_type=password&scope=trust&username=" + login + "&password=" + password , "", { headers: headers })
.map((response: Response) => response.json())
.subscribe(response => {
this.accessToken = response.access_token; //will be used for socket
}
);
第三套接字配置:
@Configuration
@EnableWebSocket
public class SocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(socketHandler(), "/websocket").setAllowedOrigins("*");
}
@Bean
public SocketHandler socketHandler() {
return new SocketHandler();
}
}
public class SocketHandler extends TextWebSocketHandler {
@Autowired
private CheckTokenEndpoint checkTokenEndpoint;
private static Logger logger = LoggerFactory.getLogger(SocketHandler.class);
public void afterConnectionEstablished(WebSocketSession session) {
logger.info("New peer connected: " + session.getId());
}
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
logger.debug("Peer is trying to authenticate");
String token = message.getPayload().toString();
try {
checkTokenEndpoint.checkToken(token);
logger.info("New peer authenticated. ");
} catch (Exception e) {
logger.warn("Peer unauthenticated!");
session.close(); //closing connection when provided token doesn't match
}
}
}
最后,通过angular2建立连接:
let ws = new WebSocket("localhost:8080/websocket", []);
ws.onopen = (event: Event) => {
this.send(
ws.send()
});
如果您只是 copy/paste,此代码可能无法正常工作。我还有其他几个案例要处理(即我的 websocket 正在重新建立连接)。因为它们不在问题范围内,所以我在此处放置代码时手动删除了它们。
对不起,一开始我的语言不好。我是一名来自德国的学生,刚开始编程。
我已经使用 Spring Boot 实现了一个小型 websocket 服务器,并使用 Basic Auth 通过 Spring Security 对其进行了保护。 Angular 2 用于前端。我已经实现了以下解决方案来连接到 websocket。
* Connects to a websocket server. * @param {string} url The url of the WS Server * @param {string} channel The channel to subscribe * @return {boolean} connection status */ public connect(url: string, channel: string): boolean { console.group('WebSocketService: Welcome to the connect function.'); console.log('Connects to', url); console.log('Channel is', channel); let _self = this; let socket = new SockJS(url);
_self.wsClient = Stomp.over(socket);
_self.wsClient.connect({}, function(frame) {
_self.setConnected(true);
console.log('Connected: ', frame);
_self.wsClient.subscribe(channel, function(greeting) {
console.log(greeting);
_self.subjects[channel].next(greeting);
});
});
console.groupEnd();
return true;
}
调用此函数让浏览器打开用户名和密码输入。 现在我可以连接和断开与服务器的连接,无需再次输入用户名/密码。
如何使用代码中的登录信息替换此浏览器输入 window?
我试图通过一个 Post 请求来做到这一点,例如:
private test2(){ let username : string = 'admin'; let password : string = 'pass'; let headers = new Headers(); headers.append("Authorization", "Basic " + btoa(username + ":" + password)); headers.append("Content-Type", "application/x-www-form-urlencoded"); console.log('Test beginnt'); return this._http.get('http://localhost:8080/gs-guide-websocket', {headers: headers}).map(res=> console.log(res)) }
Blockquote
但这只给我一个 http 200 响应,并没有打开会话或其他东西。
我也试过将登录信息放在原始请求中。
_self.wsClient.connect('admin','pass', function(frame) { ...}
感谢您的帮助。
我没有使用过 SockJS。但是我已经为纯 WebSocket 实现了一些小机制。也许会有帮助
首先,OAUTH配置:
@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
private static Logger logger = LoggerFactory.getLogger(OAuth2Configuration.class);
private UsersService service = new UsersService();
@Autowired
AuthenticationManagerBuilder authenticationManager;
@Autowired
UserDetailsService userDetailsService;
@Override
public void configure( AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
authenticationManager.userDetailsService(this.userDetailsService);
endpoints.authenticationManager((Authentication authentication) -> authenticationManager.getOrBuild().authenticate(authentication));
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("application_name")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("write", "read", "trust")
.secret("secret").accessTokenValiditySeconds(24 * 60 * 60);
}
@Bean
public UserDetailsService userDetailsService() {
return (username) -> {
return service.getByName(username).map(account -> new User(account.getName(), account.getPassword(), account.getAuthorities())).orElseThrow(
() -> new RuntimeException("User not found")
);
};
}
}
第二,angular2授权:
let headers = new Headers();
headers.append("Authorization", "Basic appname:secret");
this.http.post("localhost:8080/oauth_endpoint?grant_type=password&scope=trust&username=" + login + "&password=" + password , "", { headers: headers })
.map((response: Response) => response.json())
.subscribe(response => {
this.accessToken = response.access_token; //will be used for socket
}
);
第三套接字配置:
@Configuration
@EnableWebSocket
public class SocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(socketHandler(), "/websocket").setAllowedOrigins("*");
}
@Bean
public SocketHandler socketHandler() {
return new SocketHandler();
}
}
public class SocketHandler extends TextWebSocketHandler {
@Autowired
private CheckTokenEndpoint checkTokenEndpoint;
private static Logger logger = LoggerFactory.getLogger(SocketHandler.class);
public void afterConnectionEstablished(WebSocketSession session) {
logger.info("New peer connected: " + session.getId());
}
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
logger.debug("Peer is trying to authenticate");
String token = message.getPayload().toString();
try {
checkTokenEndpoint.checkToken(token);
logger.info("New peer authenticated. ");
} catch (Exception e) {
logger.warn("Peer unauthenticated!");
session.close(); //closing connection when provided token doesn't match
}
}
}
最后,通过angular2建立连接:
let ws = new WebSocket("localhost:8080/websocket", []);
ws.onopen = (event: Event) => {
this.send(
ws.send()
});
如果您只是 copy/paste,此代码可能无法正常工作。我还有其他几个案例要处理(即我的 websocket 正在重新建立连接)。因为它们不在问题范围内,所以我在此处放置代码时手动删除了它们。