春季安全 - 基于令牌身份验证API和放大器;用户名/密码认证 [英] Spring Security - Token based API auth & user/password authentication

查看:205
本文介绍了春季安全 - 基于令牌身份验证API和放大器;用户名/密码认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个web应用,将主要提供使用Spring REST API,并正尝试配置安全的一面。

I am trying to create a webapp that will primarily provide a REST API using Spring, and am trying to configure the security side.

我想实现这种模式:<一href=\"https://developers.google.com/accounts/docs/MobileApps\">https://developers.google.com/accounts/docs/MobileApps (谷歌已经完全改变了该网页,所以不再有意义 - 见我指的是这里的页面:<一href=\"http://web.archive.org/web/20130822184827/https://developers.google.com/accounts/docs/MobileApps\">http://web.archive.org/web/20130822184827/https://developers.google.com/accounts/docs/MobileApps)

I am trying to implement this kind of pattern: https://developers.google.com/accounts/docs/MobileApps (Google have totally changed that page, so no longer makes sense - see the page I was referring to here: http://web.archive.org/web/20130822184827/https://developers.google.com/accounts/docs/MobileApps)

下面是我需要accompish:

Here is what I need to accompish:


  • 网络应用已经与正常的春天用户名/密码认证工作的简单登录/注册表单(以前使用DAO / AuthenticationManager会做这种类型的事情/的UserDetailsS​​ervice等)

  • REST API终点是无状态的会话,并提供与请求每一个请求验证的基于令牌的奥纳

(例如用户登录/签约使用普通的形式,web应用提供了,然后可以在下面的API请求中使用的令牌安全cookie)

(e.g. user logins/signs up using normal forms, webapp provides secure cookie with token that can then be used in following API requests)

我有一个正常的身份验证设置如下:

I had a normal authentication setup as below:

@Override protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            .antMatchers("/mobile/app/sign-up").permitAll()
            .antMatchers("/v1/**").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/")
            .loginProcessingUrl("/loginprocess")
            .failureUrl("/?loginFailure=true")
            .permitAll();
}

我想加一个pre-auth的过滤器,先检查请求的令牌,然后设置安全上下文(将意味着,正常以下认证会被跳过?),但是,超越普通用户/密码,我没有做太多的基于令牌的安全性,但基于一些其他的例子,我想出了以下内容:

I was thinking of adding a pre-auth filter, that checks for the token in the request and then sets the security context (would that mean that the normal following authentication would be skipped?), however, beyond the normal user/password I have not done too much with token based security, but based on some other examples I came up with the following:

安全配置:

@Override protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .disable()
            .addFilter(restAuthenticationFilter())
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint()).and()
                .antMatcher("/v1/**")
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/mobile/app/sign-up").permitAll()
                .antMatchers("/v1/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/")
                .loginProcessingUrl("/loginprocess")
                .failureUrl("/?loginFailure=true")
                .permitAll();
    }

我的自定义过滤休息:

My custom rest filter:

public class RestAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public RestAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    private final String HEADER_SECURITY_TOKEN = "X-Token"; 
    private String token = "";


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        this.token = request.getHeader(HEADER_SECURITY_TOKEN);

        //If we have already applied this filter - not sure how that would happen? - then just continue chain
        if (request.getAttribute(FILTER_APPLIED) != null) {
            chain.doFilter(request, response);
            return;
        }

        //Now mark request as completing this filter
        request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

        //Attempt to authenticate
        Authentication authResult;
        authResult = attemptAuthentication(request, response);
        if (authResult == null) {
            unsuccessfulAuthentication(request, response, new LockedException("Forbidden"));
        } else {
            successfulAuthentication(request, response, chain, authResult);
        }
    }

    /**
     * Attempt to authenticate request - basically just pass over to another method to authenticate request headers 
     */
    @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        AbstractAuthenticationToken userAuthenticationToken = authUserByToken();
        if(userAuthenticationToken == null) throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
        return userAuthenticationToken;
    }


    /**
     * authenticate the user based on token, mobile app secret & user agent
     * @return
     */
    private AbstractAuthenticationToken authUserByToken() {
        AbstractAuthenticationToken authToken = null;
        try {
            // TODO - just return null - always fail auth just to test spring setup ok
            return null;
        } catch (Exception e) {
            logger.error("Authenticate user by token error: ", e);
        }
        return authToken;
    }

以上实际上导致错误应用程序启动时说:的AuthenticationManager必须指定
谁能告诉我如何更好地做到这一点 - 是pre_auth过滤做到这一点的最好办法

The above actually results in an error on app startup saying: authenticationManager must be specified Can anyone tell me how best to do this - is a pre_auth filter the best way to do this?

修改

我写了什么,我发现我如何与Spring的安全性(包括code)执行一个标准的token(没有的OAuth)做到了。

I wrote up what I found and how I did it with Spring-security (including the code) implementing a standard token implementation (not OAuth)

<一个href=\"http://automateddeveloper.blogspot.co.uk/2014/03/securing-your-api-for-mobile-access.html\">Overview这个问题和方法/解决方案

<一个href=\"http://automateddeveloper.blogspot.co.uk/2014/03/securing-your-mobile-api-spring-security.html\">Implementing与Spring安全解决方案

希望它可以帮助一些人。

Hope it helps some others..

推荐答案

我相信你提到的错误仅仅是因为你使用的是 AbstractAuthenticationProcessingFilter 基类需要一个的AuthenticationManager 。如果你不打算使用它,你可以将其设置为空操作,或只是实施过滤器直接。如果你的过滤器可以验证请求,并设置了 SecurityContext的则通常是下游加工将被跳过(这取决于下游滤波器的实现,但我没有看到任何奇怪的在你的应用程序,所以他们大概都表现得这样)。

I believe the error that you mention is just because the AbstractAuthenticationProcessingFilter base class that you are using requires an AuthenticationManager. If you aren't going to use it you can set it to a no-op, or just implement Filter directly. If your Filter can authenticate the request and sets up the SecurityContext then usually the downstream processing will be skipped (it depends on the implementation of the downstream filters, but I don't see anything weird in your app, so they probably all behave that way).

如果我是你,我可能会考虑投入一个完全独立的过滤器链的API端点(另一个 WebSecurityConfigurerAdapter 豆)。但这只会使事情更容易阅读,不一定是至关重要的。

If I were you I might consider putting the API endpoints in a completely separate filter chain (another WebSecurityConfigurerAdapter bean). But that only makes things easier to read, not necessarily crucial.

您可能会发现(如在评论建议),您最终会重新发明轮子,但没有试图伤害,你可能会更多地了解Spring和安全的过程中。

You might find (as suggested in comments) that you end up reinventing the wheel, but no harm in trying, and you will probably learn more about Spring and Security in the process.

增加: GitHub的办法是很有趣:用户只需使用该令牌作为基本身份验证密码,该服务器不需要自定义过滤器( BasicAuthenticationFilter一样是罚款)

ADDITION: the github approach is quite interesting: users just use the token as a password in basic auth, and the server doesn't need a custom filter (BasicAuthenticationFilter is fine).

这篇关于春季安全 - 基于令牌身份验证API和放大器;用户名/密码认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆