基于请求参数的Spring安全认证

标签 spring authentication spring-security url-parameters

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

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

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

我查看了 Spring Security 文档,想知道 AbstractPreAuthenticatedProcessingFilter 是否是正确的开始?

最佳答案

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

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

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 以将自定义参数转换为身份验证 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:

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

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

<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)。

关于基于请求参数的Spring安全认证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19791406/

相关文章:

linux - 登录 CLearOS webconfig 失败

java - 假而不是真(@gmail.com)

java - 两个 Web 应用程序之间共享身份验证和 SSO

java - 如何在不使用 ComponentScan 的情况下启动 Spring Boot Web 应用程序

java - Spring Data Cassandra - 检索受影响的行

java - 从 Java 代码调用 Spring 组件

spring - 使用多个 AuthenticationProvider 时如何从 PreAuthenticatedAuthenticationProvider 重定向 UsernameNotFoundException?

java - Spring 启动: keywords supported for JPA

java - Excel/OLAP 和 HTTP 基本授权 - Excel 能否记住它已登录?

java - 带有 Java 配置的 Spring OAuth2 的最简单示例是什么?