2013-02-20 37 views
1

我正在尝试为我的Web应用程序使用Spring安全性。我即将开始登录功能,因此用户可以登录到我的网站中的受保护页面。到目前为止,我一直在使用Spring安全性,在这里我使用内存数据存储进行身份验证(主要是为了测试它是否工作,因为我仍在学习)。我从内存数据存储切换到使用弹簧安全数据库后无法登录

我的问题发生在我尝试在我存储了不同用户的地方使用我的数据库。当我尝试登录,春季安全重定向我到我的“认证失败,网址”,而不是登录我进去。

我创建了一个自定义的UserDetails类

package dk.chakula.web.security; 

import dk.chakula.web.domain.User; 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
/** 
* 
* @author Martin Rohwedder 
* @since 20-02-2013 
* @version 1.0 
*/ 
public class ChakulaUserDetails implements UserDetails { 

    private User user; 
    private List<? extends GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 

    public ChakulaUserDetails(User user, List<? extends GrantedAuthority> authorities)   { 
     this.user = user; 
     this.authorities = authorities; 
    } 

    @Override 
    public Collection<? extends GrantedAuthority> getAuthorities() { 
     return authorities; 
    } 

    @Override 
    public String getPassword() { 
     return this.user.getPassword(); 
    } 

    @Override 
    public String getUsername() { 
     return this.user.getUsername(); 
    } 

    @Override 
    public boolean isAccountNonExpired() { 
     return true; 
    } 

    @Override 
    public boolean isAccountNonLocked() { 
     return true; 
    } 

    @Override 
    public boolean isCredentialsNonExpired() { 
     return true; 
    } 

    @Override 
    public boolean isEnabled() { 
     return true; 
    } 

} 

我也创建一个自定义UserDetailsS​​ervice,这是我的'认证提供者'引用的。那堂课看起来像这样。

package dk.chakula.web.security; 

import dk.chakula.web.domain.User; 
import dk.chakula.web.service.UserService; 
import java.util.ArrayList; 
import java.util.List; 
import org.apache.commons.lang.StringUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Component; 
/** 
* 
* @author Martin Rohwedder 
* @since 20-02-2013 
* @version 1.0 
*/ 
@Component("chakulaUserDetailsService") 
public class ChakulaUserDetailsService implements UserDetailsService { 

    @Autowired 
    private UserService userService; 

    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     if (StringUtils.isBlank(username)) { 
      throw new UsernameNotFoundException("Username was empty"); 
     } 

     User user = userService.getUserByUsername(username); 

     if (user == null) { 
      throw new UsernameNotFoundException("User with username '" + username + "' was not found"); 
     } 

     List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(); 
     grantedAuthorities.add(new SimpleGrantedAuthority(user.getUserRole())); 

     return new ChakulaUserDetails(user, grantedAuthorities); 
    } 

} 

我充满春天的安全上下文看起来像这样

<?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:security="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <security:http use-expressions="true"> 

     <!-- Form Login Filter --> 
     <security:form-login login-page="/login" default-target-url="/app/start" authentication-failure-url="/login?authenticationNok=1" username-parameter="username" password-parameter="password" always-use-default-target="true" /> 

     <!-- Logout Filter --> 
     <security:logout logout-success-url="/home?logoutOk=1" logout-url="/logout" invalidate-session="true" /> 

     <!-- Intercept Url filters --> 
     <security:intercept-url pattern="/" access="permitAll" /> 
     <security:intercept-url pattern="/home" access="permitAll" /> 
     <security:intercept-url pattern="/about" access="permitAll" /> 
     <security:intercept-url pattern="/login" access="permitAll" /> 
     <security:intercept-url pattern="/resources/**" access="permitAll" /> 

     <security:intercept-url pattern="/app/**" access="fullyAuthenticated" /> 

    </security:http> 

    <bean id="chakulaUserDetailsService" class="dk.chakula.web.security.ChakulaUserDetailsService" /> 

    <security:authentication-manager> 
     <security:authentication-provider user-service-ref="chakulaUserDetailsService"> 
      <security:password-encoder hash="sha-256"> 
       <security:salt-source user-property="username" /> 
      </security:password-encoder> 
      <!-- 
      <security:user-service> 
       <security:user name="test" password="e9233bd61e14137a7e28f92c50ce279215e774a1772d1e9dad5f275b9cc8177c" authorities="ROLE_CUSTOMER" /> 
      </security:user-service> 
      --> 
     </security:authentication-provider> 
    </security:authentication-manager> 

</beans> 

你可以在GitHub上我Chakula项目的所有源代码,进去一看,如果你需要用它来帮助我 - https://github.com/martin-rohwedder/chakula

+0

你的'UserDetailsS​​ervice'返回正确的用户吗? – 2013-02-21 03:10:52

+0

您是否检查过数据库中的密码加密? – 2013-02-21 03:12:06

+1

在'failure-url'中,您可以使用'Exception ex =(AuthenticationException)request.getSession()。getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION));'找出失败的原因 – 2013-02-21 03:14:28

回答

0

这一切似乎都是我的Dao实现类的失败,因为当我显示AuthenticationException的消息时,它告诉我以下内容 - 无法解析属性:USERNAME:dk.chakula.web.domain.User [from dk .chakula.web.domain.User你在哪里美国ERNAME =:USERNAME]

我所要做的就是用非大写字母写u.USERNAME。

改写我的安全上下文xml文件的形式登录标签authentication-failure-url属性与下面的值,而不是。

<security:form-login login-page="/login" default-target-url="/app/start" authentication-failure-url="/login/failure" username-parameter="username" password-parameter="password" always-use-default-target="true" /> 

此后我在我的AuthenticationController提出了新的方法来呈现故障视图,并为模型添加的AuthenticationException消息视图

@RequestMapping(value = {"/login/failure"}, method = RequestMethod.GET) 
public ModelAndView renderLoginFailureView(HttpServletRequest request) { 
    ModelAndView mav = new ModelAndView("login"); 
    AuthenticationException authEx = (AuthenticationException) request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); 

    mav.addObject("authEx", authEx.getMessage()); 
    return mav; 
} 

下一次,我知道要显示所有异常消息然后冲入栈溢出。尽管现在其他人可能会在未来的答案中受益。

感谢Arun P Johny帮助我在这里。