2013-01-10 40 views
9

Tôi khá mới vào mùa xuân và đang giải quyết vấn đề này với bảo mật mùa xuân. Thực ra nó chỉ hoạt động mà không cần cài đặt UserDetailsService tùy chỉnh của tôi.Bảo mật mùa xuân - UserDetailsService implementation - Đăng nhập Fails

Tài khoản và Vai trò Objects

@Entity 
@Table(name="ACCOUNT", uniqueConstraints = {@UniqueConstraint (columnNames = "USERNAME"),  @UniqueConstraint (columnNames = "EMAIL")}) 
public class Account implements Serializable { 
private static final long serialVersionUID = 2872791921224905344L; 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name="ID") 
private Integer id; 

@Column(name="USERNAME") 
@NotNull 
private String username; 

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

@Column(name="EMAIL") 
@NotNull 
@Email 
private String email; 

@Column(name="ENABLED") 
private boolean enabled; 

@ManyToMany(cascade= CascadeType.ALL) 
@JoinTable(name="ACCOUNT_ROLE", joinColumns = {@JoinColumn (name="ID_ACCOUNT")}, inverseJoinColumns ={ @JoinColumn (name="ID_ROLE")}) 
private Set<Role> roles = new HashSet<Role>(0); 

Vai trò

@Entity 
@Table(name="ROLE", uniqueConstraints={@UniqueConstraint (columnNames="NAME")}) 
public class Role implements Serializable{ 

private static final long serialVersionUID = -9162292216387180496L; 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Integer id; 

@Column(name = "NAME") 
@NotNull 
private String name; 

@ManyToMany(mappedBy = "roles") 
private Set<Account> accounts = new HashSet<Account>(0); 

Các bộ chuyển đổi cho UserDetails

@SuppressWarnings({ "serial", "deprecation" }) 
public class UserDetailsAdapter implements UserDetails { 

private Account account; 

public UserDetailsAdapter(Account account) {this.account = account;} 

public Account getAccount() {return account;} 

public Integer getId(){return account.getId();} 

public String getEmail() {return account.getEmail();} 

@Override 
public Collection<? extends GrantedAuthority> getAuthorities() { 
    Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(); 
    for (Role r :account.getRoles()) { 
     authorities.add(new GrantedAuthorityImpl(r.getName())); 
    } 
    return authorities; 
} 

Các UserDetailsService tùy chỉnh

@Service("customUserDetailsService") 
public class CustomUserDetailsService implements UserDetailsService { 
@Inject AccountDao accountDao; 
@Inject RoleDao roleDao; 


@Override 
public UserDetails loadUserByUsername(String username) 
     throws UsernameNotFoundException { 
    Account account= accountDao.findByUsername(username); 



    if(account==null) {throw new UsernameNotFoundException("No such user: " + username); 
    } else if (account.getRoles().isEmpty()) { 
     throw new UsernameNotFoundException("User " + username + " has no authorities"); 
       } 
    UserDetailsAdapter user = new UserDetailsAdapter(account); 
    return user; 
    } 

Các web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

<filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
</filter-mapping> 

<!-- The definition of the Root Spring Container shared by all Servlets and Filters --> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/spring/root-context.xml 
        /WEB-INF/spring/appServlet/security- context.xml</param-value> 
</context-param> 

<!-- Creates the Spring Container shared by all Servlets and Filters --> 
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<!-- Creates the Filters to handle hibernate lazyload exception --> 

<filter> 
    <filter-name>OpenSessionInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>OpenSessionInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 


<!-- Processes application requests --> 
<servlet> 
    <servlet-name>appServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>appServlet</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 

</web-app> 

gốc ngữ cảnh

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:p="http://www.springframework.org/schema/p" 
xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> 

<!-- Root Context: defines shared resources visible to all other web components --> 
<context:property-placeholder properties-ref="deployProperties"/> 
<!-- Remember to correctly locate the right file for properties configuration(example DB connection parameters) --> 
<bean id="deployProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean" 
    p:location="/WEB-INF/spring/appServlet/spring.properties" /> 

    <context:annotation-config/> 
    <context:component-scan base-package="org.treci"> 
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 
    </context:component-scan> 

    <import resource="/appServlet/data-context.xml"/> 

Bối cảnh an ninh

<?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:p="http://www.springframework.org/schema/p" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> 

<http pattern="/resources" security="none" /> 


<http auto-config="true" use-expressions="true"> 
    <intercept-url pattern="/" access="permitAll"/> 
    <intercept-url pattern="/login" access="permitAll"/> 
    <intercept-url pattern="/login-success" access="hasRole('ROLE_ADMIN')"/> 

    <form-login login-page="/login" 
    default-target-url="/login-success" 
    authentication-failure-url="/login-failed"/> 
    <logout logout-success-url="/logout"/> 
</http> 

<beans:bean id="customUserDetailsService" class="org.treci.app.service.CustomUserDetailsService"></beans:bean> 


<authentication-manager> 
    <authentication-provider user-service-ref="customUserDetailsService"> 
    </authentication-provider> 
</authentication-manager> 

</beans:beans> 

Tôi hy vọng một số bạn có thể giúp đỡ, cứu tôi:)

+2

Bạn có bất cứ bản ghi? Tôi có vấn đề tương tự khi UserDetailsService của tôi không phải là @Transactional. – madhead

+0

Chính xác nó không hoạt động như thế nào? –

+0

sau khi cung cấp tên người dùng và mật khẩu, nó luôn mang đến cho tôi quyền xác thực-thất bại-url = "/ login-failed"/ Truy cập dữ liệu vào DB đang hoạt động thực sự gây ra việc tôi đang in trên trang web công việc của DAO –

Trả lời

10

Dưới đây là cách tôi giải quyết sự cố:

trong CustomDetailsService Tôi đã trả về đối tượng UserDetails bằng cách sử dụng Bộ điều hợp như bạn có thể thấy.

Nhìn vào một số hướng dẫn tôi nhận ra rằng tôi nên trả về một đối tượng org.springframework.security.core.userdetails.User.

Dưới đây là thực hiện CustomDetailsService mới của tôi:

@Transactional(readOnly=true) 
@Service("customUserDetailsService") 
public class CustomUserDetailsService implements UserDetailsService { 
@Inject AccountDao accountDao; 

@Override 
public UserDetails loadUserByUsername(String username) 
     throws UsernameNotFoundException { 
    Account account= accountDao.findByUsername(username); 

    if(account==null) {throw new UsernameNotFoundException("No such user: " + username); 
    } else if (account.getRoles().isEmpty()) { 
     throw new UsernameNotFoundException("User " + username + " has no authorities"); 
       } 

    boolean accountNonExpired = true; 
    boolean credentialsNonExpired = true; 
    boolean accountNonLocked = true; 

    return new User(
      account.getUsername(), 
      account.getPassword().toLowerCase(), 
      account.isEnabled(), 
      accountNonExpired, 
      credentialsNonExpired, 
      accountNonLocked, 
      getAuthorities(account.getRoles())); 
    } 

public List<String> getRolesAsList(Set<Role> roles) { 
    List <String> rolesAsList = new ArrayList<String>(); 
    for(Role role : roles){ 
     rolesAsList.add(role.getName()); 
    } 
    return rolesAsList; 
} 

public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) { 
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    for (String role : roles) { 
     authorities.add(new SimpleGrantedAuthority(role)); 
    } 
    return authorities; 
} 

public Collection<? extends GrantedAuthority> getAuthorities(Set<Role> roles) { 
    List<GrantedAuthority> authList = getGrantedAuthorities(getRolesAsList(roles)); 
    return authList; 
} 

} 
+1

Nếu bạn đang sử dụng LDAP để xác thực, một cơ sở dữ liệu cho ủy quyền vai trò và không muốn chuyển mật khẩu cho UserDetailsService, bạn có thể chuyển một chuỗi (tức là "LDAP"). Nó sẽ không chấp nhận một giá trị null. –

+0

Vì vậy, bạn không sử dụng lớp UserDetailsAdapter của bạn sau đó? – Stephane

Các vấn đề liên quan