【问题标题】:Remember me in REST using Spring security使用 Spring 安全性在 REST 中记住我
【发布时间】:2015-07-27 18:53:41
【问题描述】:

我需要创建“记住我”提供的 REST 服务。我的应用程序应该接收带有登录数据的 JSON,对用户进行身份验证,并使应用程序能够记住用户。我已经编写了一些代码 sn-p,其中几乎没有模拟 @RequestMapping 和简单的 Spring 安全配置,但是,应用程序对用户进行身份验证(因为成功的Authentication()过滤器的方法调用)。但是,即使在登录操作之后,当我尝试向安全 url 发送请求时,它也会返回 401 代码。我知道,很明显,新请求会创建一个新会话,但是有没有办法在每个请求正文中不发送登录信息的情况下执行“记住我”行为?这是我的一些代码:

package com.checkpoint.aimer.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

public class RestSecurityFilter extends AbstractAuthenticationProcessingFilter{

    public RestSecurityFilter(String url, AuthenticationManager m) {
        super(url);
        this.setAuthenticationManager(m);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException,
            IOException, ServletException {
        HttpSession session = request.getSession();

        Authentication auth = this.getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken("roman", "sawawluha"));
        SecurityContextHolder.getContext().setAuthentication(auth);

        return auth;
    }
}

安全配置:

package com.checkpoint.aimer.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public RestSecurityFilter restSecurity() throws Exception {
        RestSecurityFilter filter = new RestSecurityFilter("/auth/login_test", authenticationManagerBean());
        return filter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public UserDetailsService usr() {
        return new UserSecurityService();
    }

    @Override 
    public void configure(HttpSecurity http) throws Exception{
        http
            .httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint() {

                @Override
                public void commence(HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException arg2) throws IOException, ServletException {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Oops");

                }
            }).and()
            .addFilterBefore(restSecurity(),BasicAuthenticationFilter.class )
            .rememberMe().rememberMeServices(new TokenBasedRememberMeServices("key",usr()) ).and()
            .authorizeRequests()
                .antMatchers("/**").hasRole("USER")
                .antMatchers("/auth/**").anonymous()
                .and()
            .csrf().disable()
            .logout().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth
            .userDetailsService(usr());
    }



}

你有什么想法吗?

【问题讨论】:

    标签: java spring rest spring-security


    【解决方案1】:

    记住我的功能主要是基于 cookie 实现的。您可以将一些身份验证令牌存储到 cookie 中。我相信您甚至可以为此使用会话 Cookie。

    但请记住:

    • 你必须一直使用 HTTPS
    • 一直使用HttpOnly cookie 属性
    • 一直使用Secure cookie 属性

    因为 cookie 是随每个请求发送给客户端的,所以您需要确保它是通过安全通道发送的,并且不会被跨站攻击访问。

    【讨论】:

    • 你的意思是 - 服务器会创建一个 httpOnlysecure cookie 来保存访问令牌,然后服务器将其设置到浏览器?然后这个 cookie 会随每个请求一起发送,这样就解决了 REST 中的 remember-me 功能,而这个 remember-me 将取决于 cookie 的过期时间?
    • 令牌需要在服务器上过期。您不能依赖客户端来使 cookie 过期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 2015-04-10
    • 2017-12-05
    相关资源
    最近更新 更多