2013-01-10 16 views
9

मैं बसंत के लिए काफी नया हूं और वसंत सुरक्षा के साथ इस मुद्दे को रोक रहा हूं। वास्तव में यह केवल मेरे कस्टम UserDetailsService कार्यान्वयन के बिना काम करता है।वसंत सुरक्षा - उपयोगकर्ता विवरण सेवा कार्यान्वयन - लॉगिन विफलता

खाता और भूमिका ऑब्जेक्ट्स

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

भूमिका

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

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

कस्टम UserDetailsService के लिए एडाप्टर

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

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> 

रूट संदर्भ

<?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"/> 

सुरक्षा संदर्भ

<?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> 

मुझे आशा है कि आप में से कुछ मदद कर सकते हैं, मुझे बचाओ:)

+2

आप किसी भी लॉग है? मुझे एक ही समस्या है जब मेरा UserDetailsService @ ट्रांसेक्शनल नहीं था। – madhead

+0

यह वास्तव में कैसे काम नहीं कर रहा है? उपयोगकर्ता नाम और पासवर्ड देने के बाद –

+0

यह मुझे हमेशा प्रमाणीकरण-विफलता-यूआरएल = "/ लॉगिन-असफल"/ डीबी तक डेटा पहुंच वास्तव में काम कर रहा है क्योंकि मैं वेब पेज पर डीएओ का काम कर रहा हूं –

उत्तर

10

यहां बताया गया है कि मैंने समस्या का हल कैसे किया:

कस्टमडिल्स सेवा में मैं एडाप्टर का उपयोग करके उपयोगकर्ता विवरण वस्तु को वापस कर रहा था जैसा कि आप देख सकते हैं।

कुछ ट्यूटोरियल को देखते हुए मुझे एहसास हुआ कि मुझे एक org.springframework.security.core.userdetails.User ऑब्जेक्ट वापस करना चाहिए।

यह मेरा नया CustomDetailsService कार्यान्वयन है:

@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

यदि आप प्रमाणीकरण के लिए एलडीएपी का उपयोग कर रहे हैं, भूमिका प्राधिकरण के लिए एक डेटाबेस, और UserDetailsService पर पासवर्ड पास नहीं करना चाहते हैं, तो आप इसके बजाय एक स्ट्रिंग (यानी "एलडीएपी") पास कर सकते हैं। यह एक शून्य मूल्य स्वीकार नहीं करेगा। –

+0

तो क्या आप अपने UserDetailsAdapter क्लास का उपयोग नहीं कर रहे हैं? – Stephane

संबंधित मुद्दे