ZK + Spring Framework + HibernateにSpring Securityをデプロイする:パート2

すべての良い一日。 この記事は、Webアプリケーションにセキュリティを実装する方法に関する記事の続きです。 基礎として、 この投稿で説明したアプリケーションを使用します。

作業計画:





順番に始めましょう。 ユーザーとそのロールが保存されたテーブルを少し変更します。つまり、idフィールドをusersテーブルに追加します。 そして、USER_ROLEという新しいテーブルを作成します。

CREATE TABLE user_role (id NUMBER NOT NULL, name VARCHAR2(10 BYTE) NOT NULL)
      
      





また、バンドルMを整理するためのテーブルを作成します:1、user_role_list

 CREATE TABLE user_role_list (id_user NUMBER NOT NULL, id_role NUMBER NOT NULL)
      
      





マッピングクラスについて説明します。 次のコンテンツを含むUserクラスを作成します。

 package com.sample.data; import java.io.Serializable; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "USERS") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id private long id; @Column(name = "USERNAME") private String username; @Column(name = "PASSWORD") private String password; @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) Set<Role> roleList; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Set<Role> getRoleList() { return roleList; } public void setRoleList(Set<Role> roleList) { this.roleList = roleList; } }
      
      







また、Roleクラスも必要です。

 package com.sample.data; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "USER_ROLE") public class Role implements Serializable { private static final long serialVersionUID = 1L; @Id private long id; @Column(name = "NAME") private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinTable(name = "USER_ROLE_LIST", joinColumns = @JoinColumn(name = "ID_ROLE"), inverseJoinColumns = @JoinColumn(name = "ID_USER")) private User user; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
      
      





コーID_USERおよびID_ROLEフィールドを持つUSER_ROLE_LIST。

また、hibernate-config.xmlファイルに次を追加します。

 <mapping class="com.sample.data.User" /> <mapping class="com.sample.data.Role" />
      
      





計画に基づいて、承認フォームを変更するか、jspページの代わりにzkページを作成し、機能をわずかに変更します。 認証フォームでは、ユーザー入力ではなく、リストからのユーザー選択を行います。 index.zulファイルを作成し、WebContentフォルダーに配置します

 <?page id="testZul" title=" "?> <window title="" border="normal" width="500px" mode="modal" position="center" use="ui.component.Login" id="wndLogin"> <html style="color:red" if="${not empty param.login_error}"> <![CDATA[   ,   ,   <br/><br/> <!-- Reason: --> <!-- ${SPRING_SECURITY_LAST_EXCEPTION.message} --> ]]> </html> <groupbox> <h:form id="f" name="f" action="j_spring_security_check" method="POST" xmlns:h="http://www.w3.org/1999/xhtml"> <grid> <rows> <row> : <combobox id="cbUser" name="j_username" hflex="1" value="" /> </row> <row> : <textbox id="p" type="password" name="j_password" hflex="1" value="" /> </row> <row visible="false"> <checkbox id="r" name="_spring_security_remember_me" /> </row> <row spans="2"> <vbox align="center" hflex="1"> <hbox> <h:input type="submit" value="" /> <h:input type="reset" value="" /> </hbox> </vbox> </row> </rows> </grid> </h:form> </groupbox> </window>
      
      





その後、use = "ui.component.Login"という行で示したコントローラーについて説明します。

 package ui.component; import java.util.List; import javax.servlet.ServletContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.zkoss.zul.Combobox; import org.zkoss.zul.Window; import com.sample.data.User; import com.sample.service.ISecur; public class Login extends Window { private static final long serialVersionUID = 3974533449164635181L; private ISecur userDao; private Combobox cbUser; private List<User> listUser; public void onCreate() { ApplicationContext ctx = WebApplicationContextUtils. getRequiredWebApplicationContext((ServletContext) getDesktop().getWebApp() .getNativeContext()); userDao = (ISecur) ctx.getBean("securImpl"); cbUser = (Combobox) this.getFellow("cbUser"); onOpenCB(); } public void onOpenCB() { if (listUser == null || listUser.size() == 0) { listUser = userDao.findAllUsers(); for (User pers : listUser) { cbUser.appendItem(pers.getUsername()); } } } }
      
      





テーブルUSERS、USER_ROLE_LIST、およびUSER_ROLEを操作するためのインターフェイスについて説明し、その実装を記述します。

ISecurインターフェイス:

 package com.sample.service; import java.util.List; import com.sample.data.User; public interface ISecur { List<User> findAllUsers(); }
      
      





SecurImplインターフェースの実装

 package com.sample.service; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.sample.data.User; @Repository @Transactional(readOnly = true) public class SecurImpl implements ISecur { private static SessionFactory sessionFactory; //   datasource @Autowired public void setSessionFactory(SessionFactory sessionFactory) { SecurImpl.sessionFactory = sessionFactory; } @SuppressWarnings("unchecked") @Override public List<User> findAllUsers() { return (List<User>) sessionFactory.getCurrentSession().createQuery("from User").list(); } }
      
      





次の非常に重要なステップは、AbstractUserDetailsAuthenticationProviderクラスから継承されたメソッドをオーバーライドすることです。 この新しい継承クラス(MyDaoAuthenticationProviderと呼びましょう)には、承認のロジックが含まれます。

 package com.sample.service; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.sample.data.Role; @SuppressWarnings("deprecation") @Service("myDaoAuthenticationProvider") public class MyDaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { @Bean public ISecur userDao() { return new SecurImpl(); } public Authentication authenticate(Authentication authentication) throws AuthenticationException { System.out.println(authentication.getName() + " " + new Date()); return super.authenticate(authentication); } @Override protected void additionalAuthenticationChecks(UserDetails arg0, UsernamePasswordAuthenticationToken arg1) throws AuthenticationException { } @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken userInfo) throws AuthenticationException { List<com.sample.data.User> listUser = userDao().findAllUsers(); User user; if (listUser.size() == 0) { throw new UsernameNotFoundException("    "); } com.sample.data.User person = getUser(listUser, username); if(person.getPassword().equals(userInfo.getCredentials().toString())) { user = new User(person.getUsername(), userInfo.getCredentials().toString(), true, true, true, true, getAuthorities((Set<Role>) person.getRoleList())); } else { user = new User(person.getPassword(), userInfo.getCredentials().toString(), true, true, true, false, getAuthorities("IS_AUTHENTICATED_ANONYMOUSLY")); } return user; } private com.sample.data.User getUser(List<com.sample.data.User> lp, String userName) { com.sample.data.User pers = null; for (com.sample.data.User p : lp) { if (userName.equals(p.getUsername())) { pers = p; } } return pers; } private Collection<GrantedAuthority> getAuthorities(Set<Role> set) { Collection<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(); for (Role role : set) { authList.add(new GrantedAuthorityImpl(role.getName())); } return authList; } private Collection<GrantedAuthority> getAuthorities(String grant_name) { Collection<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(); authList.add(new GrantedAuthorityImpl(grant_name)); return authList; } }
      
      





「ログイン」ボタンがクリックされると、保護されたUserDetails retrieveUserメソッドが呼び出されます。

このメソッドでは、選択したユーザーと入力されたパスワードとの対応を比較し、すべてが問題ない場合、UserDetailsインターフェイスの実装であるUserクラスを作成し、 ユーザーに関するすべての必要な情報(ユーザー名、パスワード、権利のリスト)を含めます。

ここで、MyDaoAuthenticationProviderクラスをプロバイダーとして使用する必要があることをAuthenticationManagerに伝えます。 このため、行の代わりにspring-config.xmlファイルで:

 <security:authentication-manager> <security:authentication-provider> <security:jdbc-user-service data-source-ref="dataSource" /> </security:authentication-provider> </security:authentication-manager>
      
      





以下を書いてください:

 <security:authentication-manager> <security:authentication-provider ref="userDetailsService"> </security:authentication-provider> </security:authentication-manager>
      
      





ここで説明されているhttp設定を次のように変更することも非常に重要です。

 <security:http auto-config="true" use-expressions="true"> <security:intercept-url pattern="/index.zul" access="hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/login.zul" access="permitAll" /> <security:form-login login-page="/login.zul" always-use-default-target="true" default-target-url="/index.zul" authentication-failure-url="/login.zul?login_error=1" /> </security:http>
      
      





以上です! アプリケーションを起動すると、美しい承認フォームが表示され、ドロップダウンリストからユーザーを選択できます。

ご清聴ありがとうございました。



All Articles