Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使Spring安全性接受JSON而不是表单参数?_Java_Spring Boot_Spring Security_Jhipster - Fatal编程技术网

Java 如何使Spring安全性接受JSON而不是表单参数?

Java 如何使Spring安全性接受JSON而不是表单参数?,java,spring-boot,spring-security,jhipster,Java,Spring Boot,Spring Security,Jhipster,我试图更改JHipster,使其使用JSON对象进行身份验证,而不是表单参数。我已经设法使它的JWT身份验证机制起作用。现在,我想为其他身份验证选项执行此操作 有没有一种简单的方法来更改Spring Security的默认安全配置以允许这样做?以下是JHipster现在使用的内容: .and() .rememberMe() .rememberMeServices(rememberMeServices) .rememberMeParameter("remember-me")

我试图更改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}

我做过这样的事。解决方案并不难,但我做到了创建一个主要基于UserNamePasswordAuthenticationFilter的自定义安全过滤器的技巧

实际上,您应该重写attemptAuthentication方法。仅仅覆盖ActainPassword和ActainUserName可能不会被启用,因为您想要读取请求正文,并且必须同时为这两个参数执行此操作(如果您不创建一种多读HttpServletRequest包装器)

解决方案必须如下所示:

    public class JsonUserNameAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
    //[...]
    public Authentication attemptAuthentication(HttpServletRequest request,
                HttpServletResponse response) throws AuthenticationException {
            if (postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException(
                        "Authentication method not supported: " + request.getMethod());
            }

    UsernamePasswordAuthenticationToken authRequest =
            this.getUserNamePasswordAuthenticationToken(request);

            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);

            return this.getAuthenticationManager().authenticate(authRequest);
        }
        //[...]

protected UserNamePasswordAuthenticationToken(HttpServletRequest request){
    // here read the request body and retrieve the params to create a UserNamePasswordAuthenticationToken. You may use jackson of whatever you like most
}
//[...]
}
然后您必须配置它。对于这种复杂的配置,我总是使用基于xml的配置

    <beans:bean id="jsonUserNamePasswordAuthenticationFilter" 
                class="xxx.yyy.JsonUserNamePasswordAuthenticationFilter">
            <beans:property name="authenticationFailureHandler>
                <beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                    <!-- set the failure url to a controller request mapping returning failure response body.
                    it must be NOT secured -->
                </beans:bean>
            </beans:property>
            <beans:property name="authenticationManager" ref="mainAuthenticationManager" />
            <beans:property name="authenticationSuccessHandler" >
                <beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                    <!-- set the success url to a controller request mapping returning success response body.
                    it must be secured -->
                </beans:bean>
            </beans:property>
        </beans:bean>

        <security:authentication-manager id="mainAuthenticationManager">                
            <security:authentication-provider ref="yourProvider" />
        </security:authentication-manager>

<security:http pattern="/login-error" security="none"/>
    <security:http pattern="/logout" security="none"/>

<security:http pattern="/secured-pattern/**" auto-config='false' use-expressions="false"
        authentication-manager-ref="mainAuthenticationManager" 
        create-session="never" entry-point-ref="serviceAccessDeniedHandler">
        <security:intercept-url pattern="/secured-pattern/**" access="ROLE_REQUIRED" />
        <security:custom-filter ref="jsonUserNamePasswordAuthenticationFilter" 
            position="FORM_LOGIN_FILTER" />     
        <security:access-denied-handler ref="serviceAccessDeniedHandler"/>
        <security:csrf disabled="true"/>
    </security:http>


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

这使用了SpringSecurity4.2,WebSecurity配置适配器。在那里,我没有使用
…formLogin()…
,而是编写了一个自己的配置程序,在可用时使用JSON,如果不可用则默认为Form(因为我需要这两种功能)

我从
org.springframework.security.config.annotation.web.configurers.formloginconfiguler
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
中复制了所有需要呈现的内容(但我并不在意)

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

最后是实际解析JSON的过滤器。代码示例是一个类,因此可以直接复制

/**WebSecurityConfig,允许使用JSON Post请求进行身份验证*/
@配置
@EnableWebSecurity(调试=false)
公共类WebSecurityConfig扩展了WebSecurityConfigureAdapter{
//资源在这里
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
//在这里,您需要配置路径、身份验证提供程序等。
//最初这是http.formLogin().loginPage。。。
http.apply(新的JSonLoginConfiguler()
.loginPage(“/authenticate”)
.successHandler(新的SimpleLauthenticationSuccessHandler(“/dashboard”))
.permitAll());
}
/**这是强制JSONAuthenticationFilter的配置程序。
*基于org.springframework.security.config.annotation.web.configurers.FormLoginConfiguler
*/
私有类JSONLoginConfiguler扩展
AbstractAuthenticationFilterConfigure{
公共JSONLoginConfiguler(){
super(新的JSONAuthenticationFilter(),null);
}
@凌驾
公共JSONLoginConfiguration登录页面(字符串登录页面){
返回super.loginPage(loginPage);
}
@凌驾
受保护的请求匹配器createLoginProcessingUrlMatcher(字符串loginProcessingUrl){
返回新的AntPathRequestMatcher(loginProcessingUrl,“POST”);
}
}
/**这是实际处理json的过滤器
*/
私有类JSONAuthenticationFilter扩展了UsernamePasswordAuthenticationFilter{
受保护字符串获取密码(JsonObject obj){
返回obj.getString(getPasswordParameter());
}
受保护字符串获取用户名(JsonObject obj){
返回obj.getString(getUsernameParameter());
}
@凌驾
公共身份验证尝试身份验证(HttpServletRequest请求、HttpServletResponse响应)
抛出AuthenticationException{
if(!“application/json”.equals(request.getContentType())){
//请注意,UsernamePasswordAuthenticationFilter中的objtainPassword和Username
//具有不同的方法签名
返回super.attemptAuthentication(请求、响应);
}
try(BufferedReader=request.getReader()){
//使用javax.json.json进行json转换
JsonObject obj=Json.createReader(reader.readObject();
字符串用户名=获取用户名(obj);
字符串密码=获取密码(obj);
UsernamePasswordAuthenticationTokenAuthRequest=新UsernamePasswordAuthenticationToken(
用户名、密码);
返回此.getAuthenticationManager().Authentication(authRequest);
}捕获(IOEX异常){
抛出新的AuthenticationServiceException(“解析请求失败”,ex);
}
}
}
}

你能看看这篇文章吗:XML配置完全崩溃了。请参阅。@您确定吗?这个回复已经有一段时间了,但它是从一个测试和工作的例子。到底什么东西坏了?当然,有些元素没有配置,只是放在xml注释标记的地方,但在我编写我的answer@jlumietu是的,非常肯定<第10行的代码>
没有结束标记,第1行的代码>没有结束标记。要正确,您必须将第15行的
替换为
@Younes您是否已使用设置填补了注释中的空白?等等,我发现了一个输入错误…我从loginPage方法启动时收到一个异常,它太长,无法作为注释发布,原因是:java.lang.IllegalStateException:securityBuilder不能在org.springframework.security.config.annotation.SecurityConfigureAdapter.getBuilder(SecurityC