0

我正在尝试为 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.");
}

一旦客户端通过身份验证,在登录期间,我不希望它在调用 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
    }

}

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

客户端代码:

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

@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();

我正在尝试类似地编写“播放”的客户端代码,但不需要传递身份验证标头。我觉得,我应该以某种方式在请求标头中传递与会话相关的参数,以通知服务器它是同一会话的一部分,但无法弄清楚如何做到这一点。

4

1 回答 1

1

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

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

有可能自己摆弄会话ID,但我不推荐它。

于 2015-01-08T19:18:00.537 回答