Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.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,Spring security:Spring security返回302,即使登录失败_Java_Spring_Spring Mvc_Spring Security - Fatal编程技术网

Java Spring,Spring security:Spring security返回302,即使登录失败

Java Spring,Spring security:Spring security返回302,即使登录失败,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,我正在开发一个SpringMVC应用程序,其中我使用SpringSecurity进行身份验证和授权。我正在使用RestTemplate通过Android连接到webapp 目前,我遇到的问题是,即使登录失败,我也会收到302而不是200。因此,在客户端,我不知道登录失败了。之后,当用户尝试访问安全资源时,访问被拒绝,应用程序死亡 有人能告诉我当登录失败时如何返回正确的响应代码,以及如何通过响应代码检测它吗。非常感谢 securityApplicationContext.xml: <sec

我正在开发一个SpringMVC应用程序,其中我使用SpringSecurity进行身份验证和授权。我正在使用RestTemplate通过Android连接到webapp

目前,我遇到的问题是,即使登录失败,我也会收到302而不是200。因此,在客户端,我不知道登录失败了。之后,当用户尝试访问安全资源时,访问被拒绝,应用程序死亡

有人能告诉我当登录失败时如何返回正确的响应代码,以及如何通过响应代码检测它吗。非常感谢

securityApplicationContext.xml:

 <security:http pattern="/resources/template/demo/clients" security="none"/>

    <security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
        <security:form-login login-page="/login" username-parameter="j_username" password-parameter="j_password"
                             login-processing-url="/j_spring_security_check" default-target-url="/dashboard"
                             always-use-default-target="true" authentication-failure-url="/denied"/>
        <security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService"
                              token-validity-seconds="1209600" data-source-ref="dataSource"/>
        <security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
        <!--<security:intercept-url pattern="/**" requires-channel="https"/>-->
        <security:port-mappings>
            <security:port-mapping http="80" https="443"/>
        </security:port-mappings>
        <security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>

        <security:session-management session-fixation-protection="migrateSession">
            <security:concurrency-control session-registry-ref="sessionReg" max-sessions="5" expired-url="/sessionexpired"/>
        </security:session-management>
    </security:http>

    <beans:bean id="sessionReg" class="org.springframework.security.core.session.SessionRegistryImpl"/>

    <beans:bean id="rememberMeAuthenticationProvider"
                class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:constructor-arg index="0" value="_spring_security_remember_me"/>
        <beans:constructor-arg index="1" ref="userDetailsService"/>
        <beans:constructor-arg index="2" ref="jdbcTokenRepository"/>
        <property name="alwaysRemember" value="true"/>
    </beans:bean>

    <beans:bean id="jdbcTokenRepository"
                class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <beans:property name="createTableOnStartup" value="false"/>
        <beans:property name="dataSource" ref="dataSource"/>
    </beans:bean>

    <!-- Remember me ends here -->
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider user-service-ref="LoginServiceImpl">
            <security:password-encoder ref="encoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <beans:bean id="encoder"
                class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="11"/>
    </beans:bean>

    <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
        <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>
</beans>

在Android方面,我是如何进行身份验证的:

    private class LoginUserViaRest extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {

            final EditText userEmail = (EditText) findViewById(R.id.usernameText);
            final EditText userPassword = (EditText) findViewById(R.id.PasswordField);

            rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
            StaticRestTemplate.jsessionid = rest.execute(StaticRestTemplate.baseURL+"j_spring_security_check", HttpMethod.POST,
                    new RequestCallback() {
                        @Override
                        public void doWithRequest(ClientHttpRequest request) throws IOException {
                            request.getBody().write(("j_username=" + userEmail.getText().toString() + "&j_password=" + userPassword.getText().toString()).getBytes());
                        }
                    }, new ResponseExtractor<String>() {
                        @Override
                        public String extractData(ClientHttpResponse response) throws IOException {
// Here I can get the code to determine if login was successful
                            List<String> cookies = response.getHeaders().get("Cookie");
                            if (cookies == null) {
                                cookies = response.getHeaders().get("Set-Cookie");
                            }
                            String cookie = cookies.get(cookies.size() - 1);
                            int start = cookie.indexOf('=');
                            int end = cookie.indexOf(';');

                            return cookie.substring(start + 1, end);
                        }
                    });
            return null;

        }

        @Override
        protected void onPostExecute(String aVoid) {
            super.onPostExecute(aVoid);
        }
    }
私有类LoginUserSet扩展异步任务{
@凌驾
受保护字符串doInBackground(无效…参数){
最终EditText userEmail=(EditText)findViewById(R.id.usernameText);
最终的EditText用户密码=(EditText)findViewById(R.id.PasswordField);
添加(新的MappingJackson2HttpMessageConverter());
StaticRestTemplate.jsessionid=rest.execute(StaticRestTemplate.baseURL+“j_spring_security_check”,HttpMethod.POST,
新的RequestCallback(){
@凌驾
public void doWithRequest(ClientHttpRequest请求)引发IOException{
request.getBody().write(((“j_username=“+userEmail.getText().toString()+”&j_password=“+userPassword.getText().toString()).getBytes());
}
},新的响应抽取器(){
@凌驾
公共字符串提取数据(ClientHttpResponse响应)引发IOException{
//在这里,我可以获得确定登录是否成功的代码
List cookies=response.getHeaders().get(“Cookie”);
如果(cookies==null){
cookies=response.getHeaders().get(“设置Cookie”);
}
字符串cookie=cookies.get(cookies.size()-1);
int start=cookie.indexOf('=');
int end=cookie.indexOf(“;”);
返回cookie.substring(开始+1,结束);
}
});
返回null;
}
@凌驾
受保护的void onPostExecute(字符串避免){
super.onPostExecute(避免);
}
}
如果有任何进一步的解释,请让我知道。非常感谢。:-)

更新

Login.jsp:

<div class="col-xs-12 col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-4 col-lg-offset-4">
        <div class="container-fluid white-div">
            <div class="col-xs-12 col-md-12">
                <h2><spring:message code="login.title"/></h2>
                <form id="login-form" class="login-page" action="<c:url value='/j_spring_security_check'/>" method="POST">
                    <div class="form-group">
                        <label><spring:message code="login.label.email"/> <span id="eMailError" class="red-font"></span></label>
                        <div class="wrapper">
                            <input type="email" name="j_username" id="j_username" value="" class="form-control input" placeholder="<spring:message code="common.input.email.placeholder"/>">
                            <i class="fa fa-user"></i>
                        </div>
                    </div>
                    <div class="form-group">
                        <label><spring:message code="login.label.password"/> <span id="passwordError" class="red-font"></span></label>
                        <div class="wrapper">
                            <input type="password" name="j_password" id="j_password"  class="form-control input"  placeholder="<spring:message code="login.password.placeholder"/>">
                            <i class="fa fa-lock"></i>
                        </div>
                    </div>
                    <div class="checkbox">
                        <div class="col-xs-5">
                            <div class="row">
                                <label class="pull-left" for="show-password">
                                    <input type="checkbox" id="show-password"><spring:message code="common.label.showpassword"/>
                                </label>
                            </div>
                        </div>
                        <a href="#" class="forgotpassword pull-right" data-toggle="modal" data-target="#passwordForgotModal"><spring:message code="login.forgotpassword"/></a>
                    </div>
                    <br>
                    <div class="form-group">
                        <button class="btn btn-primary btn-lg pull-right"><spring:message code="login.submit"/></button>
                    </div>
                    <div class="form-group">
                        <span><spring:message code="login.registration.text"/> <a href="/registration" class="forgotpassword"><spring:message code="login.registration.link"/></a></span>
                    </div>
                </form>
            </div>
        </div>
    <!--    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div> -->
        <c:if test="${not empty url}">
            <%-- <a href="${url}" class="btn btn-primary btn-lg btn-block si-facebook si-colored verticalAlignCenter"><spring:message code="common.facebook"/></a> --%>
        </c:if>
    </div>
</div>



安全性:表单登录是为web应用而不是REST客户端设计的。虽然你可以使用它,但你会遇到你在这里描述的那种麻烦

我建议改用
security:httpbasic
(通过HTTPS进行安全保护)并每次发送登录详细信息

编辑:如果您坚持使用表单登录,您需要告诉
restemplate
不要遵循重定向,这可以通过以下操作实现(使用Apache HttpComponents而不是标准的JRE
HttpUrlConnection
):


安全性:表单登录
是为web应用而不是REST客户端设计的。虽然你可以使用它,但你会遇到你在这里描述的那种麻烦

我建议改用
security:httpbasic
(通过HTTPS进行安全保护)并每次发送登录详细信息

编辑:如果您坚持使用表单登录,您需要告诉
restemplate
不要遵循重定向,这可以通过以下操作实现(使用Apache HttpComponents而不是标准的JRE
HttpUrlConnection
):


当然,您将得到一个302,因为这是登录过滤器所做的,它重定向到最初请求的URL。如果您不想这样做,请不要使用登录表单。@M.Deinum:Rest应该指向哪个URL?您必须为此创建一些内容。…@M.Deinum:Oh!!。你有任何链接有任何例子或类似的东西吗?我不知道从哪里开始。非常感谢。@M.Deinum:我有一个login.jsp,先生,我将用户名和密码传递给Spring security。你能帮助我理解如何将其与Spring Security集成吗。我正在更新我的主要帖子,包括它的内容。谢谢。当然你会得到一个302,因为登录过滤器就是这么做的,它会重定向到最初请求的URL。如果您不想这样做,请不要使用登录表单。@M.Deinum:那么我应该使用Rest指向哪个URL?您必须为此创建一些内容…@M.D
    final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    final HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(
            new DefaultRedirectStrategy() {
                @Override
                public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
                    return false;
                }
            }
    ).build();
    factory.setHttpClient(httpClient);
    restTemplate.setRequestFactory(factory);