gpt4 book ai didi

java - Spring,Spring-security : Spring-security returning 302, 即使登录失败

转载 作者:行者123 更新时间:2023-11-30 03:13:50 26 4
gpt4 key购买 nike

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

目前,我遇到的问题是,即使登录失败,我也会收到 302 而不是 200。因此,在客户端我不知道登录已失败。此后,当用户尝试访问 protected 资源时,访问将被拒绝并且应用程序将终止。

谁能告诉我如何在登录失败时返回正确的响应代码以及如何通过响应代码检测它。多谢。

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);
}
}

如果需要任何进一步的解释,请告诉我。多谢。 :-)

更新

登录.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>

最佳答案

security:form-login 是为 Web 应用程序而不是 REST 客户端设计的。尽管您可以使用它,但您会遇到此处描述的那种麻烦。

我建议使用 security:http-basic (通过 HTTPS 保护)并每次发送登录详细信息。

编辑:如果您坚持使用表单登录,则需要告诉 RestTemplate 不要遵循重定向,您可以使用以下方法执行此操作(使用 Apache HttpComponents 而不是标准 JRE HttpUrlConnection):

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

关于java - Spring,Spring-security : Spring-security returning 302, 即使登录失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33083076/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com