如何使Spring Security接受JSON而不是表单参数? [英] How to make Spring Security accept JSON instead of form parameters?

查看:326
本文介绍了如何使Spring Security接受JSON而不是表单参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试更改JHipster,因此它使用JSON对象而不是表单参数进行身份验证.我已经设法使其JWT身份验证机制起作用.现在,我想将其用于其他身份验证选项.

I'm trying to change JHipster so it uses a JSON object for authentication instead of form parameters. I've managed to make this work for its JWT authentication mechanism. Now I'd like to do it for other authentication options.

是否有一种简单的方法可以更改Spring Security的默认安全配置以允许此操作?这是JHipster现在使用的方法:

Is there an easy way to change Spring Security's default security configuration to allow this? Here's what JHipster uses now:

.and()
    .rememberMe()
    .rememberMeServices(rememberMeServices)
    .rememberMeParameter("remember-me")
    .key(env.getProperty("jhipster.security.rememberme.key"))
.and()
    .formLogin()
    .loginProcessingUrl("/api/authentication")
    .successHandler(ajaxAuthenticationSuccessHandler)
    .failureHandler(ajaxAuthenticationFailureHandler)
    .usernameParameter("j_username")
    .passwordParameter("j_password")
    .permitAll()

我想将以下内容作为JSON而不是表单参数发送:

I'd like to send the following as JSON instead of form parameters:

{username: "admin", password: "admin", rememberMe: true}

推荐答案

我只需要非常相似的东西,所以我写了它.

I just needed something very similar, so I wrote it.

这使用Spring Security 4.2 WebSecurityConfigurationAdapter.在那里,我没有使用...formLogin()...,而是编写了自己的配置器,该配置器在可用时使用JSON,如果没有,则默认为Form(因为我需要两种功能).

This uses Spring Security 4.2, WebSecurityConfigurationAdapter. There instead of using ...formLogin()... I wrote an own Configurer that uses JSON when available and defaults to Form if not (because I need both functionalities).

我从org.springframework.security.config.annotation.web.configurers.FormLoginConfigurerorg.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter复制了需要呈现的所有内容(但我不在乎),这些地方的源代码和文档对我有很大帮助.

I copied all things that needed to be present (but I didn't care about) from org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer and org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter where the source code and documentation greatly helped me.

很有可能您还需要复制其他功能,但原则上应该这样做.

It is well possible that you will need to copy over other functions as well, but it should do in principle.

实际上是解析JSON的筛选器.该代码示例是一类,因此可以直接复制.

The Filter that actually parses the JSON is in the end. The code sample is one class so can be copied over directly.

/** WebSecurityConfig that allows authentication with a JSON Post request */
@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // resources go here
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // here you will need to configure paths, authentication provider, etc.

        // initially this was http.formLogin().loginPage...

        http.apply(new JSONLoginConfigurer<HttpSecurity>()
                  .loginPage("/authenticate")
                  .successHandler(new SimpleUrlAuthenticationSuccessHandler("/dashboard"))
                  .permitAll());
    }

    /** This is the a configurer that forces the JSONAuthenticationFilter.
     * based on org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer
     */
    private class JSONLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
              AbstractAuthenticationFilterConfigurer<H, JSONLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {

        public JSONLoginConfigurer() {
            super(new JSONAuthenticationFilter(), null);
        }

        @Override
        public JSONLoginConfigurer<H> loginPage(String loginPage) {
            return super.loginPage(loginPage);
        }

        @Override
        protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
            return new AntPathRequestMatcher(loginProcessingUrl, "POST");
        }

    }

    /** This is the filter that actually handles the json
     */
    private class JSONAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

        protected String obtainPassword(JsonObject obj) {
            return obj.getString(getPasswordParameter());
        }

        protected String obtainUsername(JsonObject obj) {
            return obj.getString(getUsernameParameter());
        }

        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) 
                  throws AuthenticationException {
            if (!"application/json".equals(request.getContentType())) {
                // be aware that objtainPassword and Username in UsernamePasswordAuthenticationFilter
                // have a different method signature
                return super.attemptAuthentication(request, response);
            }

            try (BufferedReader reader = request.getReader()) {

                //json transformation using javax.json.Json
                JsonObject obj = Json.createReader(reader).readObject();
                String username = obtainUsername(obj);
                String password = obtainPassword(obj);

                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                          username, password);

                return this.getAuthenticationManager().authenticate(authRequest);
            } catch (IOException ex) {
                throw new AuthenticationServiceException("Parsing Request failed", ex);
            }
        }
    }
}

这篇关于如何使Spring Security接受JSON而不是表单参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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