使用UserDetailsS​​ervice和Hibernate的SpringSecurity表单登录 [英] SpringSecurity form login using UserDetailsService and Hibernate

查看:114
本文介绍了使用UserDetailsS​​ervice和Hibernate的SpringSecurity表单登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直使用Spring Security在SpringMVC中创建有用的表单登录。我在这方面很新手,也是Hibernate。我想创建一个简单的表单登录,它可以访问我的Web应用程序。



我使用SpringSource Tool Suite创建了我的项目并选择了Spring Template Project。它使用Maven,我也通过Hibernate类生成注释和 hibernate.cfg.xml 。在我的数据库(HSQLDB)中,我有三个表:用户,角色和users_roles。第三个包含user_id和role_id,因此它存储有关用户角色的信息。我已经通过Hibernate生成了类。



我已经开始编写实现UserDetailsS​​ervice的类。但我不知道如何正确地做到这一点。在> spring-security.xml 中定义了这样的bean:

  < bean id =userDetailsS​​erviceclass =hutter.pl.services.HutterUserDetailsS​​ervice/> 

我想使用sha-256与saltSource进行哈希处理。

 < bean class =org.springframework.security.authentication.dao.ReflectionSaltSourceid =saltSource> 
< property name =userPropertyToUsevalue =username/>
< / bean>

< security:authentication-manager>
< security:authentication-provider user-service-ref =userDetailsS​​ervice>
< security:password-encoder hash =sha-256>
< security:salt-source ref =saltSource/>
< / security:password-encoder>
< / security:authentication-provider>
< / security:authentication-manager>

我应该使用这个解决方案: https://stackoverflow.com/a/1654488/845220 ? Hibernate拥有类似的类:RolesHome,Roles,Users,UsersHome,UsersRoles,UsersRolesHome。但我真的不知道如何使用这些Hibernates类来授权用户。

  @Service(userDetailsS​​ervice)
public class MyUserDetailsS​​ervice implements UserDetailsS​​ervice {

@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)引发UsernameNotFoundException {
UsersHome usersHome = new UsersHome();
//用户用户= ...
// ...
返回null;


$ / code $ / pre

你能给我一些提示吗?



编辑:
我尝试添加方法 public Users findByLogin(String login) UsersHome 类。

  public用户findByLogin(String login){ 
log.debug(使用登录获取用户实例:+登录);
尝试{
Users instance = entityManager.find(Users.class,login);
log.debug(get success);
返回实例;
} catch(RuntimeException re){
log.error(get failed,re);
throw re;


我的UserDetailsS​​ervice的正文如下所示:

  UsersHome usersHome = new UsersHome(); 
用户user = usersHome.findByLogin(用户名);

但是我得到了一些建议:

 错误:my.package.dao.UsersHome  - 获取失败
my.package.dao.UsersHome.findByLogin中的java.lang.NullPointerException
(UsersHome.java:72 )
at my.package.services.HutterUserDetailsS​​ervice.loadUserByUsername(MyUserDetailsS​​ervice.java:19)


解决方案

我认为你不需要自己实现UserService。您可以对数据源使用 jdbc-user-service

  < bean id =dataSourceclass =org.apache.commons.dbcp.BasicDataSource> 
< property name =driverClassNamevalue =com.mysql.jdbc.Driver/>
< property name =usernamevalue =root/>
< property name =passwordvalue =password/>
< / bean>

< authentication-manager>
< authentication-provider>
users-by-username-query =select username,password,enabled from users where username =?
authorities-by-username-query =从用户u中选择u.username,ur.authority,在u.user_id = ur.user_id和u.username =?中选择user_roles。
/>
< / authentication-provider>
< / authentication-manager>

使用属性 users-by-username-query users-by-username-query 您可以定义spring security应该用来从数据源接收用户和权限的查询。



如果


  • 您需要实现您自己的 UserService 想要返回自定义的UserDetails对象(您可以通过 SecurityContextHolder 来访问)

  • 用户对象和权限的接收也是如此复杂和/或无法通过简单查询在 jdbc-user-service



中定义

UserDetailsS​​ervice的一个可能实现可能如下所示:

  @Service(userDetailsS​​ervice)
public class MyUserDetailsS​​ervice实现UserDetailsS​​ervice {

@PersistenceContext
私有EntityManager entityManager;

@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)引发UsernameNotFoundException {

//只有当用户名是用户的主键时
//如果不是这种情况,您必须创建一个查询对象来通过用户名接收用户
User user = entityManager.find(User.class,username);

列表<授权授权>角色= .... //获取用户的角色,取决于你的表结构

if(user == null){
//用户未找到
throw new UsernameNotFoundException ();
}
返回新的MyUserDetails(用户,角色);
}

私有静态类MyUserDetails实现UserDetails {
私有用户用户;
私人列表< Role>角色;

public MyUserDetails(Usere user,List< GrantedAuthority> roles){
this.user = user;
this.roles =角色;
}

public Collection<授权授权> getAuthorities(){
返回角色;
}

public String getPassword(){
return user.getPassword();


public String getUsername(){
return user.getUsername();
}

//为缺少的布尔方法返回true ..
}
}

(语法未选中)

对于第一次测试,它可以帮助禁用密码编码器并将未加密的密码数据库。这样可以避免由于配置错误PasswordEncoders而导致身份验证不起作用的问题。一旦你运行了你的用户服务,你可以再次添加一个PasswordEncoder并将散列的密码存储在数据库中。



希望它有帮助: - )


I have got stuck at creating usefull form login in SpringMVC using Spring Security. I'm quite newbie in this and also Hibernate. I would like to create simple form login which could provide access to my web application.

I have created my project using SpringSource Tool Suite and selecting Spring Template Project. It uses Maven and I have also generated by Hibernate classes with annotations and hibernate.cfg.xml. In my database (HSQLDB) I have three tables: users, roles and users_roles. The third one contains user_id and role_id, so it stores information about users' roles. I have generated class by Hibernate successful.

I have started writing my class implementing UserDetailsService. But I don't know how to do this properly. In spring-security.xml I have defined bean like this:

<bean id="userDetailsService" class="hutter.pl.services.HutterUserDetailsService" />

I would like to use hashing by sha-256 with saltSource.

<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
    <property name="userPropertyToUse" value="username"/>
</bean>

<security:authentication-manager>   
    <security:authentication-provider user-service-ref="userDetailsService">
        <security:password-encoder hash="sha-256">
            <security:salt-source ref="saltSource" />
        </security:password-encoder> 
    </security:authentication-provider>
</security:authentication-manager>

Should I have used this solution: https://stackoverflow.com/a/1654488/845220 ? Hibernate have generted classes like: RolesHome, Roles, Users, UsersHome, UsersRoles, UsersRolesHome. But i really don't know how to use these Hibernates classes to authorize users.

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {   
        UsersHome usersHome = new UsersHome();
       //Users user = ...       
       //...            
       return null;     
    }   
}

Could you give me some hints?

EDIT: I have tried to add method public Users findByLogin(String login) to the UsersHome class.

   public Users findByLogin(String login) {
    log.debug("getting Users instance with login: " + login);
    try {
        Users instance = entityManager.find(Users.class, login);
        log.debug("get successful");
        return instance;
    } catch (RuntimeException re) {
        log.error("get failed", re);
        throw re;
    }
}

And body of my UserDetailsService looks like:

UsersHome usersHome = new UsersHome();
Users user = usersHome.findByLogin(username);

But I have got excpetion:

 ERROR: my.package.dao.UsersHome - get failed
 java.lang.NullPointerException
at my.package.dao.UsersHome.findByLogin(UsersHome.java:72)
at my.package.services.HutterUserDetailsService.loadUserByUsername(MyUserDetailsService.java:19)

解决方案

I think you don't need to implement an UserService yourself. You can use a jdbc-user-service with a datasource:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
  <property name="username" value="root" />
  <property name="password" value="password" />
</bean>

<authentication-manager>
  <authentication-provider>
    <jdbc-user-service data-source-ref="dataSource"
      users-by-username-query="select username,password, enabled from users where username=?"
      authorities-by-username-query="select u.username, ur.authority from users u, user_roles ur  where u.user_id = ur.user_id and u.username =?" 
    />
  </authentication-provider>
</authentication-manager>

With the properties users-by-username-query and users-by-username-query you can define the queries spring security should use to receive the users and authorities from the datasource.

Implementing your own UserService is necessary if

  • you want to return customized UserDetails objects (which you can access later via the SecurityContextHolder)
  • the receival of the User objects and authorities is too complex and/or cannot be defined with easy queries at the jdbc-user-service

A possible implementation of UserDetailsService could look like this:

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

  @PersistenceContext
  private EntityManager entityManager;

  @Transactional(readOnly = true)
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {   

    // this works only if username is the primary key of user
    // if thats not the case you have to create a query object to receive the user by username
    User user = entityManager.find(User.class, username); 

    List<GrantedAuthority> roles = .... // get roles for user, depends on your table structure

    if (user == null) {
      // user not found
      throw new UsernameNotFoundException();
    }
    return new MyUserDetails(user, roles);
  }

  private static class MyUserDetails implements UserDetails {
    private User user;
    private List<Role> roles;

    public MyUserDetails(Usere user, List<GrantedAuthority> roles) {
      this.user = user;
      this.roles = roles;
    }

    public Collection<GrantedAuthority> getAuthorities() {
      return roles;
    }

    public String getPassword() {
      return user.getPassword();
    }

    public String getUsername() {
      return user.getUsername();
    }

    // return true for the missing boolean methods..
  }
}

(syntax is unchecked)

For first testing it can help to disable the password encoder and store the password unencrypted in the database. This avoids the problem that your authentication does not work because of wrongly configured PasswordEncoders. Once you have your userservice running you can then add a PasswordEncoder again and store the hashed password in the database.

Hope it helps :-)

这篇关于使用UserDetailsS​​ervice和Hibernate的SpringSecurity表单登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆