如何让 Spring Security 接受 JSON 而不是表单参数?

2023-11-26

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

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

.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 而不是表单参数发送:

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

我只是需要一些非常相似的东西,所以我写了它。

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

我复制了所有需要存在的东西(但我不关心)org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer and org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter源代码和文档对我帮助很大。

您很可能还需要复制其他函数,但原则上应该这样做。

真正解析JSON的Filter在最后。代码示例是一个类,因此可以直接复制。

/** 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);
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让 Spring Security 接受 JSON 而不是表单参数? 的相关文章

随机推荐