我尝试在登录失败时尝试在登录页面上重定向输入的用户名,但在我的控制器中,从" @ModelAttribute("用户")&#中检索用户的用户名34;一片空白。当我没有使用弹簧安全时,这是有效的。
我假设表单实际上首先弹出安全性,然后将其重定向到控制器,因此输入的信息在spring security之间丢失。
如何在不将其发送到链接参数的情况下检索用户?
PS:我试图为" / loginFailed"创建一个控制器。如果登录失败并在该控制器上使用method = RequestMethod.POST,则将其发送到那里。
LoginController
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String listPersons(@ModelAttribute("user") User u, @RequestParam(required = false) String authfailed, String logout,
String denied, Model model) {
model.addAttribute("user", u);
String message = "";
if (authfailed != null) {
message = "Invalid username or password, try again !";
} else if (logout != null) {
message = "Logged Out successfully, login again to continue !";
} else if (denied != null) {
message = "Access denied for this user !";
}
model.addAttribute("error", message);
return "login";
}
的login.jsp
<c:url var="trylogin" value="/j_spring_security_check" ></c:url>
<c:url var="register" value="/register" ></c:url>
<div id="login-box">
<form:form action="" modelAttribute="user" method="POST">
<table>
<tr>
<td> <form:label path="username"> <spring:message text="Username: "/> </form:label> </td>
<td> <form:input path="username" /> </td>
</tr>
<tr>
<td> <form:label path="password"> <spring:message text="Password: "/> </form:label> </td>
<td> <form:password path="password" /> </td>
</tr>
<tr>
<td> <input type="submit" value="<spring:message text="Login"/>"
onclick="document.getElementById('user').setAttribute('action', '${trylogin}')"/> </td>
<td> <input type="submit" value="<spring:message text="Register"/>"
onclick="document.getElementById('user').setAttribute('action', '${register}')"/> </td>
</tr>
</table>
</form:form>
<c:if test="${not empty error}">
<div class="error">${error}</div>
</c:if>
</div>
编辑(解决方案):
谢谢你@James创建一个失败的玩家是你的方法,但你的解决方案并没有很好地正常工作,因为它似乎需要&#34; p:defaultFailureUrl&#34;在failureHandler bean中,即使我有&#34; authentication-failure-url =&#34; / login?authfailed&#34;&#34;在表单登录
中<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:useForward="true"
p:defaultFailureUrl="/login"/>
之后我不得不为方法帖子添加/ login的另一个函数,因为p:defaultFailureUrl =&#34; / login?authFailed&#34;只会将其作为/ login发送,并且浏览器中的链接保持为&#34; / j_spring_security_check&#34;我无法理解为什么。
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String loginFail(@ModelAttribute("user") User u, @RequestParam(required = false) String authfailed, RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttribute("user", u);
redirectAttrs.addFlashAttribute("error", "Invalid username or password, try again !");
return "redirect:/login";
}
答案 0 :(得分:2)
您应该使用AuthenticationFailureHandler。为了您的目的,它应该足以声明Spring SimpleUrlAuthenticationFailureHandler类的bean,并指定将请求发送到目标URL而不是配置中的默认重定向行为。这样您的登录控制器就可以访问原始请求,包括用户名。
<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:useForward="true"
/>
然后在你的表单登录规范中:
<security:form-login
...
authentication-failure-handler-ref="failureHandler"
...
/>
答案 1 :(得分:0)
这是一种错误的方式。登录页面控制器仅用于查看此页面。对于支票凭证,您需要创建服务,例如:
@Service("adminDetailsServiceImpl")
public class AdminDetailsServiceImpl implements UserDetailsService {
@Autowired
private SepAdminDao adminDao;
@Override
public UserDetails loadUserByUsername(String login) {
SepAdmin admin;
if (StringUtils.isBlank(login))
throw new UsernameNotFoundException("Admin not found!");
admin = adminDao.findByEmail(login);
return new org.springframework.security.core.userdetails.User(
admin.getEmail(),
admin.getPassword(),
getGrantedAuthorities(admin.getRole().getPermissionNames()));
}
private static List<GrantedAuthority> getGrantedAuthorities(String[] roles) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles)
authorities.add(new SimpleGrantedAuthority(role));
return authorities;
}
}
使用spring分配此服务(例如我为了安全性而查看我的简单配置):
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<beans:property name="hierarchy">
<beans:value>
<!--Admin-->
PERM_ROOT > PERM_CREATE_ADMINS
PERM_CREATE_ADMINS > PERM_DELETE_ADMINS
PERM_DELETE_ADMINS > PERM_EDIT_ADMINS
PERM_EDIT_ADMINS > PERM_VIEW_ADMINS
<!--Role-->
PERM_ROOT > PERM_CREATE_ROLES
PERM_CREATE_ROLES > PERM_DELETE_ROLES
PERM_DELETE_ROLES > PERM_EDIT_ROLES
PERM_EDIT_ROLES > PERM_VIEW_ROLES
</beans:value>
</beans:property>
</beans:bean>
<beans:bean id="expressionHandler"
class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
<beans:property name="roleHierarchy" ref="roleHierarchy"/>
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
<beans:property name="expressionHandler" ref="expressionHandler"/>
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<beans:constructor-arg ref="roleHierarchy"/>
</beans:bean>
<beans:bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg value="10"/>
</beans:bean>
<http pattern="/resources/js/vendor/language" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<http auto-config="true" use-expressions="true" access-denied-page="/403"
access-decision-manager-ref="accessDecisionManager">
<intercept-url pattern="/login" access="permitAll"/>
<!--Admin-->
<intercept-url pattern="/dashboard" access="hasRole('PERM_ROOT')"/>
<intercept-url pattern="/admin/create_admin" access="hasRole('PERM_CREATE_ADMINS')"/>
<intercept-url pattern="/admin/users/*/edit_admin" access="hasRole('PERM_EDIT_ADMINS')"/>
<intercept-url pattern="/admin/users/*/view_admin" access="hasRole('PERM_VIEW_ADMINS')"/>
<intercept-url pattern="/admin/users/*/delete_admin" access="hasRole('PERM_DELETE_ADMINS')"/>
<!--Role-->
<intercept-url pattern="/role/create_role" access="hasRole('PERM_CREATE_ROLES')"/>
<intercept-url pattern="/role/*/edit_role" access="hasRole('PERM_EDIT_ROLES')"/>
<intercept-url pattern="/role/*/view_role" access="hasRole('PERM_VIEW_ROLES')"/>
<intercept-url pattern="/role/*/delete_role" access="hasRole('PERM_DELETE_ROLES')"/>
<!--Route-->
<form-login username-parameter="email"
password-parameter="password"
login-page="/login" default-target-url="/" authentication-failure-url="/login?failed"/>
<logout logout-url="/logout" logout-success-url="/login"/>
</http>
<authentication-manager alias="authManager">
<authentication-provider user-service-ref="adminDetailsServiceImpl">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
然后当用户提交登录表单时,我们会重定向到使用我们服务的/ j_spring_security_check,如果我们有登录异常,我们可以在登录jsp页面检查它:
<!-- spring_exception -->
<c:if test="${not empty SPRING_SECURITY_LAST_EXCEPTION}">
<p class="alert alert-danger alert-dismissable">
<spring:message code="Error.Msg.Login"/>
</p>
<br/>
</c:if>
如果成功,我们会重定向到默认目标网址(在我的情况下)到root。
<form-login username-parameter="email"
password-parameter="password"
login-page="/login" default-target-url="/" authentication-failure-url="/login?failed"/>
这就是为什么浏览器上的链接保持为“/ j_spring_security_check”。