如何在基于 spring 的服务器中进行 http 基本身份验证会话

How to have sessions in http basic authentication in a spring based server

我正在尝试为 android 客户端创建一个 Spring 服务器,并且正在使用基本身份验证。我有一个控制器如下:

@RequestMapping(value = "login", method = RequestMethod.GET, produces = "application/json")
public @ResponseBody Message login(HttpSession session) {
    logger.info("Accessing protected resource sid:"+session.getId());
    return new Message(100, "Congratulations!", "You have logged in.");
}

@RequestMapping(value = "play", method = RequestMethod.GET, produces = "application/json")
public @ResponseBody Message play(HttpSession session) {
    logger.info("Accessing protected play resource");
    return new Message(100, "Congratulations!", "Launching play.");
}

客户端通过身份验证后,在登录期间,我不希望它在调用播放时需要重新进行身份验证。

我的安全配置是:

 protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/signup","/about").permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);

        // @formatter:on
    }

}

我已尝试在上面启用 sessions,但如果我尝试在登录和播放的请求处理程序中打印 session id,我在使用身份验证登录后会得到不同的 id。我正在使用 HttpBasic 安全性。是否可以在 HttpBasic 安全性中使用 sessions?我读了一些文章,似乎表明它是无状态的,并且不能。有解决方法还是我必须切换到不同的安全模型?

客户代码:

在客户端,我发送如下请求登录。

@Override
    protected Message doInBackground(Void... params) {
        //final String url = getString(R.string.base_uri) + "/getmessage";
        final String url = "http://10.0.2.2:8080/login";

        // Populate the HTTP Basic Authentitcation header with the username and password
        HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setAuthorization(authHeader);
        requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

        // Create a new RestTemplate instance
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());

        try {               // Make the network request
            Log.d(TAG, url);
            ResponseEntity<Message> response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<Object>(requestHeaders), Message.class);

            if(response.getBody().getId() == 100)
                login_success = true;
            return response.getBody();

我正在尝试为 'play' 编写客户端代码,但不需要通过身份验证 header。我觉得,我应该以某种方式在请求 header 中传递一个 session 相关参数,以通知服务器它是同一 session 的一部分,但不知道该怎么做。

您正在尝试存档与会话的有状态通信,但它不会工作,因为 RestTemplate 正在以无状态方式工作。它不会保留从登录到下一次调用的状态(即会话 ID)。只有通过设置自定义 ClientHttpRequestFactory 我才能看到这项工作(我不确定 Android)。

如果你想与状态通信,你可以看看 Apache HttpClient。通过将它与您在请求之间重复使用的 HttpContext 一起使用,它将保持状态。

您可以 fiddle 使用会话 ID,但我不推荐这样做。