2012-02-21 73 views
0

我试图用Spring 3实现数据库驱动的用户登录设置。 我的日志显示用户使用登录表单中提供的用户名/密码进行了身份验证,但用户doesn由于不想将用户硬编码到配置中,因此似乎无法在JSP中访问。Spring 3将UserDetails添加到会话

感觉就像UserDetails对象由于某种原因通过session/securitycontext不可用。

在我的安全-config.xml中: 老硬编码风格。

<authentication-provider> 
    <user-service> 
     <user name="reports" password="reports" authorities="ROLE_REPORTS" /> 
     <user name="admin" password="admin" authorities="ROLE_REPORTS, ROLE_ADMIN" /> 
     <user name="super" password="super" authorities="ROLE_REPORTS, ROLE_ADMIN, ROLE_SUPER_ADMIN"/> 
    </user-service> 
</authentication-provider> 

新的身份验证提供者...

<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="userService"> 
     <!-- 
     <password-encoder ref="pwdEncoder" > 
      <salt-source ref="saltSource"/> 
     </password-encoder> 
     --> 
    </authentication-provider> 
</authentication-manager> 

片段从我userservice(它实现了Spring的UserDetailsS​​ervice接口):

@Transactional 
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException { 
    DbUser dbUser = null; 
    List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>(); 

    Session sess = sessionFactory.getCurrentSession(); 
    Query query = sess.createQuery("from DbUser where userName = '"+userName+"'"); 

    Iterator<Object> it = query.iterate(); 
    if(it.hasNext()) { 
     if(it.hasNext()) { 
      dbUser = (DbUser) it.next(); 
     } 
    } 

    if (dbUser == null) { 
     throw new UsernameNotFoundException("user not found"); 
    } else { 
     for (GrantedAuthority auth : dbUser.getRoles()) { 
      roles.add(new Role(auth.getAuthority())); 
     } 
    } 

    UserDetails springUser = null; 
    springUser = new org.springframework.security.core.userdetails.User(
     dbUser.getUserName(), 
     dbUser.getPassword().toLowerCase(), 
     dbUser.getActive(), 
     true, true, true, 
     roles); 

    return springUser; 
} 

从我的loginController:

@RequestMapping(value="/login/submit", method=RequestMethod.POST) 
public String login(Principal principle, HttpServletRequest request, ModelMap model){ 
    String username = request.getParameter("username"); 
    String password = request.getParameter("password"); 

    UserDetails springUser = null; 
    try { 
     springUser = userService.loadUserByUsername(username); 
    } catch(UsernameNotFoundException e) { 
     e.printStackTrace(); 
     model.addAttribute("message","User not found"); 
     return loginError(model); 
    } 
    if(springUser.getPassword().equals(password)){   // user/pwd combo is correct 
     /** 
     * @todo make sure user ends up as the session user here 
     */ 

// SecurityContext context = SecurityContextHolder.getContext(); // //context.setAuthentication(springUser); (“** LoginController user validated ok:”+ context.getAuthentication()。getName()); (“** LoginController principle:”+ context.getAuthentication()。getPrincipal()); } else { return loginError(model); }

Collection<GrantedAuthority> roles = springUser.getAuthorities(); 
    for(GrantedAuthority auth : roles){ 
     if(auth.getAuthority().equals(Role.ROLE_ADMIN)){ 
      return "admin/home"; 
     } 
    } 

    model.addAttribute("message", "Logged in"); 
    return "reports/summaries"; 
} 

你会在我的控制器上面,我想我会希望能够访问一个UserDetails在会话对象中看到的,但是任何记录有只返回字符串“anonymousUser”。

报告/摘要jsp显示正常,除了任何数据。没有显示包含在安全性标签中的JSP中的任何内容。 如后显然登录成功作为管理员用户缺少此块:

 <sec:authorize access="hasRole('ROLE_ADMIN')"> 
     <li> 
      <a href="<c:url value="/admin/home"/>">Admin</a> 
      <ul> 
       <li><a href="<c:url value="/admin/form/checkpoints"/>">Checkpoints</a></li> 
       <li><a href="<c:url value="/admin/form/guards"/>">Guards</a></li> 
       <li><a href="<c:url value="/admin/form/incidents"/>">Incidents</a></li> 
       <li><a href="<c:url value="/admin/form/routes"/>">Routes</a></li> 
      </ul> 
     </li> 
    </sec:authorize> 

正如你可能已经云集,我是新来春/ Spring MVC的。如果任何人都可以建议Spring认证框架的一些基本方面,我错过了这将是伟大的!

后续/编辑: 我试着恢复到@NimChimpsky在评论中建议的表单样式。我在设置2个选项进行身份验证提供者,第一,它的工作原理:

<authentication-provider> 
     <user-service> 
      <user name="reports" password="reports" authorities="ROLE_REPORTS" /> 
      <user name="admin" password="admin" authorities="ROLE_REPORTS, ROLE_ADMIN" /> 
      <user name="super" password="super" authorities="ROLE_REPORTS, ROLE_ADMIN, ROLE_SUPER_ADMIN"/> 
     </user-service> 
    </authentication-provider> 

第二,这不:

<beans:bean id="userService" class="uk.co.romar.guardian.services.UserServiceImpl" /> 

..

当我尝试使用该UserServiceImpl类进行身份验证我在Hibernate sessionFactory上得到NullPointerException,事实证明SessionFactory或我的其他服务都没有按照我的预期注入。

应该注入的sessionFactory bean在我的hibernate-context.xml中定义,它通过我的servlet.xml配置中的import语句包含。然而,身份验证提供程序在security-context.xml中声明,它不引用hibernate-context.xml。所以我将import语句复制到安全上下文中,希望能够对注入/实例化问题进行排序,但这也没有帮助。

回答

1

我认为你会让它变得比它需要的复杂,春天会为你做所有的腿。您不必编写提交登录表单的控制器。使用spring_secruity_login像这样:

<form name="f" id="f" action="<c:url value='j_spring_security_check'/>" method="POST"> 
    <label for="username">Username :&nbsp;</label> 
    <input type='text' id='j_username' name='j_username'/><br> 
    <label for="password">Password :&nbsp;</label> 
    <input type='password' id='j_password' name='j_password'><br> 

而且在登录后(仅通过提交以上表格,然后你可以在JSP中访问主要进口:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> 

然后显示(或使用getAuthorities访问角色):

Username is <sec:authentication property="principal.username" /> 
+0

感谢@NimChimpsky,我用的是形式的无控制器的风格加上我的用户服务之前,我认为控制器得到了补充阅读各种教程后,我得到。现在有一个不同的问题(SessionFactory没有被注入到用户服务中,我认为这不是相关的),当我已经排序,我会尝试返回到这种形式 – DaFoot 2012-02-21 13:45:55

+0

添加上下文:组件扫描到我的安全维护似乎已经通过注射排序了其他问题。其他问题,但我会提出新的问题。 – DaFoot 2012-02-21 17:40:48