1

SpringSecurityを使用してSpringMVCで便利なフォームログインを作成するのに行き詰まりました。私はこれとHibernateの初心者です。Webアプリケーションへのアクセスを提供できる簡単なフォームログインを作成したいと思います。

SpringSource Tool Suiteを使用し、SpringTemplateProjectを選択してプロジェクトを作成しました。これはMavenを使用しており、アノテーションとを使用してHibernateクラスによって生成されていhibernate.cfg.xmlます。私のデータベース(HSQLDB)には、users、roles、users_rolesの3つのテーブルがあります。3つ目はuser_idとrole_idが含まれているため、ユーザーの役割に関する情報が格納されます。Hibernateによるクラスの生成に成功しました。

UserDetailsS​​erviceを実装するクラスを書き始めました。しかし、これを正しく行う方法がわかりません。spring-security.xml私は次のようにBeanを定義しました:

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

saltSourceでsha-256によるハッシュを使用したいと思います。

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

このソリューションを使用する必要があります:https ://stackoverflow.com/a/1654488/845220 ?Hibernateは、RolesHome、Roles、Users、UsersHome、UsersRoles、UsersRolesHomeのようなクラスを生成しました。しかし、これらのHibernatesクラスを使用してユーザーを承認する方法が本当にわかりません。

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

ヒントを教えてください。

編集:クラスにメソッドpublic Users findByLogin(String login)を 追加しようとしました。UsersHome

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

そして、私のUserDetailsS​​erviceの本体は次のようになります。

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

しかし、私は例外を持っています:

 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)
4

1 に答える 1

7

UserServiceを自分で実装する必要はないと思います。jdbc-user-serviceデータソースでを使用できます。

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

プロパティusers-by-username-queryusers-by-username-query使用して、SpringSecurityがデータソースからユーザーと権限を受け取るために使用するクエリを定義できます。

独自の実装UserServiceが必要な場合

  • カスタマイズされたUserDetailsオブジェクトを返したい(後でアクセスできますSecurityContextHolder
  • ユーザーオブジェクトと権限の受信が複雑すぎるか、次の場所で簡単なクエリを使用して定義することはできません。jdbc-user-service

UserDetailsS​​erviceの可能な実装は次のようになります。

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

(構文はチェックされていません)

最初のテストでは、パスワードエンコーダーを無効にして、暗号化されていないパスワードをデータベースに保存すると便利です。これにより、PasswordEncodersが正しく構成されていないために認証が機能しないという問題を回避できます。ユーザーサービスを実行したら、PasswordEncoderを再度追加して、ハッシュ化されたパスワードをデータベースに保存できます。

それが役に立てば幸い :-)

于 2012-07-08T10:06:10.717 に答える