我的安全配置如下:
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username, password, activated from Person where username=?")
.authoritiesByUsernameQuery("select person.username, personrole.roleName from person, personrole, personandroles where person.username=? and personandroles.personid=person.personId and personrole.roleid=personandroles.roleid");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/empl").access("hasRole('employee')")
.antMatchers("/", "/index" , "/loginform", "/registerform","/approvelogin") .permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/loginform")
.loginProcessingUrl("/approvelogin")
.usernameParameter("username")
.passwordParameter("password")
.and()
.httpBasic().disable()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
其中/approvelogin 是我的登录控制器的名称。此控制器需要一个模型属性"人"和一个请求参数"角色"(用户可以选择要登录的角色)
在日志通知上,我有这个:
<form:form action="approvelogin" modelAttribute="userBean" method="POST">
<table>
<tr>
<td><label><b>Benutzername:</b></label>
<form:input type="text" path="username" required="true"/>
</td>
</tr>
<tr>
<td><label><b>Kennwort</b></label>
<form:input type="password" path="password" required="true">
</td>
<td>
<c:if test="${!empty roles}">
<select name="role">
<c:forEach var="r" items="${roles}">
<option value='${r.roleName}'>${r.roleName}</option>
</c:forEach>
</select>
</c:if>
</td>
<td> <input type="submit" value="Login"/>
</td>
</tr>
</table>
</form:form>
当我在浏览器中调用/empl 时,我按预期重定向到日志通知。但是在编辑了正确的用户信条后,我到达了我的 403.jsp。
在类 AuthenticationProcessingFilter 的 successlAuthentication(request、response、chain、authResult) 方法上设置断点表明"权限"集合填充了正确的角色"employee"。所以我假设其他东西会阻止我的登录控制器输入。
登录控制器:
@RequestMapping(value="/approvelogin", method=RequestMethod.POST)
public String login(@ModelAttribute("userBean") Person user, @RequestParam(value="role") String role, Model model){
if( user.getUsername().isEmpty() || user.getPassword().isEmpty() ){
model.addAttribute("error", "Please enter your username and password");
return "loginform";
}
else {
Person p = personDao.getPerson(user.getUsername(), user.getPassword());
if ( p == null) {
model.addAttribute("error", "Invalid Details, try again:");
return "loginform";
}
else{
String view="welcome";
model.addAttribute("loggedperson", p);
for( PersonRole r: p.getRoles() ){
if(r.getRoleName().equals(role)) {
view= role +"View";
break;
}
}
return view;
}
}
}
@RequestMapping(value="/empl")
public String employeeView(){
return "employeeView";
}
您的登录控制器将返回带有角色+视图的字符串,您确定您有使用此名称的视图吗?我认为您想在登录到/empl 后重定向用户。
终于我找到了解决方案。而不是设置
.loginProcessingUrl("/approvelogin")
我必须设置
.defaultSuccessUrl("/approvelogin")
显然,在 spring 完成身份验证并劝告用户继续之后,我能够访问我的自定义登录控制器,以便将用户重定向到所需的视图(根据他的角色和请求)。