Spring 3.1.1 を使用して、Spring Security と LDAP 認証を使用してアプリを開発しようとしています。また、フロントエンドには JSF 2.0 と PrimeFaces を使用します。
LDAP サーバーとナビゲーション ルールを次のように構成しました。
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="permitAll"/>
<security:intercept-url pattern="/pages/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login login-page="/login.xhtml" default-target-url="/index.xhtml"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider ref = "authProvider"/>
</security:authentication-manager>
<bean id="authProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="xxx" />
<constructor-arg value="ldap://xxx:389"/>
<property name="userDetailsContextMapper" ref = "customUserContextMapper"></property>
</bean>
<bean id="customUserContextMapper" class="CustomUserDetailsMapper"></bean>
ログインが完了した後に「ハンドラー」を配置する場所が他にわからないため、LdapUserDetailsMapper を拡張するカスタム UserDetailsMapper を作成しました。
public class CustomUserDetailsMapper extends LdapUserDetailsMapper{
private static final String ROLE_NORMAL_USER = "Normal User";
private static final String ROLE_ADMIN = "Administrator";
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx,
String username, Collection<? extends GrantedAuthority> authority) {
UserDetails originalUser = super.mapUserFromContext( ctx, username, authority );
originalUser.getAuthorities();
Set<AndaAuthority> roles = EnumSet.noneOf(AndaAuthority.class);
roles.add(AndaAuthority.ROLE_ADMIN);
for (GrantedAuthority auth : authority) {
if (ROLE_NORMAL_USER.equalsIgnoreCase(auth.getAuthority())) {
roles.add(AndaAuthority.ROLE_USER);
} else if (ROLE_ADMIN.equalsIgnoreCase(auth.getAuthority())) {
roles.add(AndaAuthority.ROLE_ADMIN);
}
}
SecurityContextHolder.getContext().getAuthentication().getCredentials();
User newUser =
new User(
originalUser.getUsername(),
originalUser.getPassword() != null? originalUser.getPassword():"",
originalUser.isEnabled(),
originalUser.isAccountNonExpired(),
originalUser.isCredentialsNonExpired(),
originalUser.isAccountNonLocked(),
roles );
return newUser;
}
}
WEB-INF のルートに login.xhtml ページがあり、ウェルカム ページとして設定しました。ここに私のweb.xmlがあります:
[..]
<!-- Welcome page -->
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<!-- JSF mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Spring Context Configuration' s Path definition -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
[..]
<!-- Spring security related configs -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
[..]
以下はログインフォームです。
<h:form action="j_spring_security_check" method="post">
<h:panelGrid columns="2">
<h:outputText value="Username" />
<h:inputText id="j_username" />
<h:outputText value="Password" />
<h:inputSecret id="j_password" />
</h:panelGrid>
<div class="submit">
<button type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
<span class="ui-button-text">Login</span>
</button>
</div>
この質問からログインページのアイデアを得ました。アクションを設定する方法がわかりませj_spring_security_check
ん../j_spring_security_check
。両方試してみましたが同じ結果でした...
何が起こるか: Tomcat でアプリを開くと、ログイン ページが表示されます。資格情報を入力すると、再度 login.xhtml にリダイレクトされ、ユーザー名だけが入力されます。
サンプルの Spring セキュリティ LDAP 統合アプリケーションで構成を使用して試したところ、ログイン部分は機能していました。そこでは、mapUserFromContext
毎回メソッドが呼び出されました。これで、ブレークポイントは入力されません。
また、サンプル アプリでは、user.passwordは常にnullで、権限リストは常に空でした。それは正常ですか?何かが壊れている場所を知るために、通常のログインをオーバーライドするより良い方法を提案できますか?
サンプルアプリはJSPで作ったので動いていたのかもしれませんが、JSFで何かを台無しにしました...
これは私の側の JSF の問題だと思いますが、その理由がわかりません。また、この場合により良い「ログイン成功ハンドラー」を実装する方法はありますか?
どうもありがとう