基于请求参数的Spring安全认证 [英] Spring security authentication based on request parameter

查看:19
本文介绍了基于请求参数的Spring安全认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发的应用程序已经有 Spring Security 来处理基于表单的身份验证.现在的要求是通过外部服务以编程方式登录用户如果在请求参数之一中找到令牌.

The application I'm working on already has Spring Security to handle form based authentication. Now the requirement is to login a user programmatically via an external service if a token is found in one of the request parameters.

换句话说,如果一个特定的请求参数,比如令牌",存在,它需要使用该令牌调用一个外部服务来验证它是否是一个有效的令牌.如果是,则用户将登录.

In other words, if a particular request parameter, say "token", exists, it needs to call an external service with that token to verify if it's a valid token. If it is then the user will be logged in.

我不知道如何以及在何处触发"或连接到"Spring Security 以检查此参数并进行验证,然后在适当的时候对用户进行身份验证,因为没有登录表单.我认为 Spring Security 中应该有一些可以扩展或定制的东西来做到这一点?

I can't figure out how and where to "trigger" or "hook on to" Spring Security to check this parameter and make the verification then authenticate the user when appropriate since there is no login form. I thought there should be something in Spring Security that can be extended or customized to do this?

我查看了 Spring Security 文档,想知道 AbstractPreAuthenticatedProcessingFilter 是否适合开始?

I looked through Spring Security documentation and wonder if AbstractPreAuthenticatedProcessingFilter is the right thing to start with?

推荐答案

我的应用程序中有类似的设置.据我所知,以下是基本要素:

I have a similar setup in my application. Here are the basic elements as far as I can tell:

您需要像这样创建一个 AuthenticationProvider:

You need to create an AuthenticationProvider like so:

public class TokenAuthenticationProvider implements AuthenticationProvider {

    @Autowired private SomeService userSvc;

    @Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        if (auth.isAuthenticated())
            return auth;

        String token = auth.getCredentials().toString();
        User user = userSvc.validateApiAuthenticationToken(token);
        if (user != null) {
            auth = new PreAuthenticatedAuthenticationToken(user, token);
            auth.setAuthenticated(true);
            logger.debug("Token authentication. Token: " + token + "; user: " + user.getDisplayName());
        } else
            throw new BadCredentialsException("Invalid token " + token);
        return auth;
    }
}

您还需要创建一个 Filter 以将自定义参数转换为身份验证令牌:

You also need to create a Filter to turn the custom parameter into an authentication token:

public class AuthenticationTokenFilter implements Filter {


    @Override
    public void init(FilterConfig fc) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
        SecurityContext context = SecurityContextHolder.getContext();
        if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
            // do nothing
        } else {
            Map<String,String[]> params = req.getParameterMap();
            if (!params.isEmpty() && params.containsKey("auth_token")) {
                String token = params.get("auth_token")[0];
                if (token != null) {
                    Authentication auth = new TokenAuthentication(token);
                    SecurityContextHolder.getContext().setAuthentication(auth);
                }
            }
        }

        fc.doFilter(req, res);
    }

    @Override
    public void destroy() {

    }

    class TokenAuthentication implements Authentication {
        private String token;
        private TokenAuthentication(String token) {
            this.token = token;
        }
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return new ArrayList<GrantedAuthority>(0);
        }
        @Override
        public Object getCredentials() {
            return token;
        }
        @Override
        public Object getDetails() {
            return null;
        }
        @Override
        public Object getPrincipal() {
            return null;
        }
        @Override
        public boolean isAuthenticated() {
            return false;
        }
        @Override
        public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        }
        @Override
        public String getName() {
            // your custom logic here
        }
    }

 }

您需要为这些创建 bean:

You need to create beans for these:

<beans:bean id="authTokenFilter" class="com.example.security.AuthenticationTokenFilter" scope="singleton" />
<beans:bean id="tokenAuthProvider" class="com.example.security.TokenAuthenticationProvider" />

最后,您需要将这些 bean 连接到您的安全配置中(相应地调整):

Finally, you need to wire these beans into your security config (adjust accordingly):

<sec:http >
   <!-- other configs here -->
   <sec:custom-filter ref="authTokenFilter" after="BASIC_AUTH_FILTER" /> <!-- or other appropriate filter -->
</sec:http>

<sec:authentication-manager>
    <!-- other configs here -->
    <sec:authentication-provider ref="tokenAuthProvider" />
</sec:authentication-manager>

可能还有另一种方式,但这绝对有效(目前使用 Spring Security 3.1).

There might be another way, but this definitely works (using Spring Security 3.1 at the moment).

这篇关于基于请求参数的Spring安全认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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