2015-09-04 97 views
0

彈簧安全的Spring MVC應用程序有三個視圖,其中包括主要公共站點/,安全站點僅用於登錄用戶/secure-home以及登錄頁面/login。當他們嘗試加載/secure-home網址時,Spring安全性已成功將所有用戶重定向到/login頁面。但問題是,將有效憑據輸入到自定義登錄頁面的用戶不被允許查看/secure-home url。如何更改代碼,以便使用有效憑據登錄的用戶重定向到/secure-home url?身份驗證在春季安全失敗,爲什麼?

注意當用戶提交不正確的憑據,即使下面的代碼jsp應打印在驗證失敗的錯誤login頁面不顯示錯誤消息。

這裏是代碼的相關方面:

SecurityConfig.java是:

@Configuration 
@EnableWebMvcSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .csrf().disable() 
      .formLogin() 
       .loginPage("/login") 
       .defaultSuccessUrl("/secure-home") 
       .usernameParameter("j_username") 
       .passwordParameter("j_password") 
       .loginProcessingUrl("/j_spring_security_check") 
       .failureUrl("/login") 
       .permitAll() 
       .and() 
      .logout() 
       .logoutUrl("/logout") 
       .logoutSuccessUrl("/login") 
       .and() 
      .authorizeRequests() 
       .antMatchers("/secure-home").hasAuthority("registered") 
       .antMatchers("/j_spring_security_check").permitAll() 
       .and() 
      .userDetailsService(userDetailsService()); 
    } 
} 

MessageWebApplicationInitializer.java是:

@Order(2) 
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { 
} 

business-config.xml包含:

<!-- lots of other stuff --> 
<bean class="my.app.config.SecurityConfig"></bean> 

mvc-core-config.java包含:

<!-- lots of other stuff --> 
<mvc:view-controller path="/" view-name="welcome" /> 
<mvc:view-controller path="/login" view-name="login" /> 

User.java是:

@Entity 
@Table(name="users") 
public class User implements UserDetails{ 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private Integer id; 

    @Column(name= "email", unique=true, nullable=false) 
    private String login;//must be a valid email address 

    @Column(name = "password") 
    private String password; 

    @Column(name = "phone") 
    private String phone; 

    @Column(name = "pin") 
    private String pin; 

    @Column(name = "sessionid") 
    private String sessionId; 

    @ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    @JoinTable(name="user_roles", 
     joinColumns = {@JoinColumn(name="user_id", referencedColumnName="id")}, 
     inverseJoinColumns = {@JoinColumn(name="role_id", referencedColumnName="id")} 
    ) 
    private Set<Role> roles; 

    public Integer getId() {return id;} 
    public void setId(Integer id) { this.id = id;} 

    public String getPhone(){return phone;} 
    public void setPhone(String pn){phone = pn;} 

    public String getPin(){return pin;} 
    public void setPin(String pi){pin = pi;} 

    public String getSessionId(){return sessionId;} 
    public void setSessionId(String sd){sessionId = sd;} 

    public String getLogin() { 
     return login; 
    } 

    public void setLogin(String login) { 
     this.login = login; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    //roles methods 
    public void addRole(Role alg) {roles.add(alg);} 
    public Set<Role> getRoles(){ 
     if(this.roles==null){this.roles = new HashSet<Role>();} 
     return this.roles; 
    } 
    public void setRoles(Set<Role> alg){this.roles = alg;} 
    public boolean isInRoles(int aid){ 
     ArrayList<Role> mylgs = new ArrayList<Role>(); 
     mylgs.addAll(this.roles); 
     for(int a=0;a<mylgs.size();a++){if(mylgs.get(a).getId()==aid){return true;}} 
     return false; 
    } 

    @Override 
    public Collection<? extends GrantedAuthority> getAuthorities() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

    @Override 
    public String getUsername() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

    @Override 
    public boolean isAccountNonExpired() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public boolean isAccountNonLocked() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public boolean isCredentialsNonExpired() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public boolean isEnabled() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

} 

Role.java是:

@Entity 
@Table(name="roles") 
public class Role implements GrantedAuthority{ 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String role; 

    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "roles") 
    private Set<User> userRoles; 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getRole() { 
     return role; 
    } 

    public void setRole(String role) { 
     this.role = role; 
    } 

    public Set<User> getUserRoles() { 
     return userRoles; 
    } 

    public void setUserRoles(Set<User> userRoles) { 
     this.userRoles = userRoles; 
    } 

    @Override 
    public String getAuthority() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 

DML來填充數據庫是:

SET FOREIGN_KEY_CHECKS=0; 
INSERT INTO `roles` VALUES (100,'registered'); 
INSERT INTO `user_roles` VALUES (100,100); 
INSERT INTO `users` VALUES (100,'[email protected]','password','phonenumber','pin','sessionid'); 
SET FOREIGN_KEY_CHECKS=1; 

而且login.jsp是:

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" 
    pageEncoding="ISO-8859-1"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> 
<title>Custom Login page</title> 
<style>.error {color: red;} 
</style> 

</head> 
<body> 
<div class="container"> 

<h1>Custom Login page</h1> 
<p> 
<c:if test="${error == true}"> 
    <b class="error">Invalid login or password.</b> 
</c:if> 
</p> 

<form method="post" action="<c:url value='j_spring_security_check'/>" > 
<table> 
<tbody> 
    <tr> 
     <td>Login:</td> 
     <td><input type="text" name="j_username" id="j_username"size="30" maxlength="40" /></td> 
    </tr> 
    <tr> 
     <td>Password:</td> 
     <td><input type="password" name="j_password" id="j_password" size="30" maxlength="32" /></td> 
    </tr> 
    <tr> 
    <td colspan=2> 
      <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 
    </td> 
    </tr> 
    <tr> 
     <td></td> 
     <td><input type="submit" value="Login" /></td> 
    </tr> 
</tbody> 
</table> 
</form> 
</div> 
</body> 
</html> 

還有一個服務層,存儲庫層和控制器來管理/secure-home URL模式的代碼。

回答

1

/secure-home僅適用於具有registered權限的用戶。

.antMatchers("/secure-home").hasAuthority("registered") 

,而您的用戶資料User.java總是返回null每當春季安全檢查驗證用戶的權限。

@Override 
public Collection<? extends GrantedAuthority> getAuthorities() { 
    // TODO Auto-generated method stub 
    return null; 
} 

試試這個

@Override 
public Collection<? extends GrantedAuthority> getAuthorities() { 
    List<GrantedAuthority> authorities = new ArrayList<>(); 
    for(Role role : roles){ 
     authorities.add(new SimpleGrantedAuthority(role.getRole())) 
    } 
    return authorities; 
}