私はSpring(および一般的なWeb開発)は初めてですが、簡単なWebアプリケーションを作成できたので、ユーザーがその機能にアクセスするにはサインインする必要があるように、それに認証サポートを追加しようとしています. .
Spring MVC 3.2.2、Spring Security 3.1.4、および Tomcat 7 を使用しています。
テスト目的で、ハードコーディングされたユーザーを使用して認証サポートを追加することができ、すべてが正しく機能しました。ここで、既存の PostgreSQL データベースを使用してユーザーを認証する必要があります。私のアプリケーションはユーザーの作成をサポートしていないことを強調したいと思います。ユーザーはすでにデータベースに保存されています。
問題は次のとおりです。
(1) アプリケーションは PostgreSQL データベースに対してユーザーを認証する必要がありますが、これを変更することはできません。
(2) データベース内のパスワードは、crypt('plain text password', gen_salt(md5)) を使用してハッシュされます。
(3) 私は注釈と xml 構成を多用したので、基本的にハードワークのほとんどは Spring によって行われます。つまり、多くのことが舞台裏で行われていることを意味します。その結果、パスワードエンコーダーがユーザーを認証するために使用する必要があるソルトの設定に行き詰まっています。そのようなソルトは、データベースに保存されているハッシュ済みのパスワードでなければなりません。
問題は
、データベースに保存されているハッシュ化されたパスワードをパスワード エンコーダーのソルトとして使用するように Spring Security に指示するにはどうすればよいかということです。xml からこれを行う方法はありますか、それとも先に進んで特定のクラスを実装する必要がありますか?
私はオンラインで広範囲に検索しましたが、これまでに見つけたすべての例は、主に組み込み機能にほとんど依存するのではなく、ほとんどの例で機能的に開発者によって実装されているため、私が行ったものからかなり逸脱しています.
これはsecurity.xmlファイルです。
<http use-expressions="true">
<intercept-url pattern="/resources/images/**" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/resources/css/**" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/login*" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/**" access="hasAnyRole('ROLE_Processer', 'ROLE_Verifier', 'ROLE_Approver', 'ROLE_Supervisor', 'ROLE_Admin')" requires-channel="any"/>
<session-management>
<concurrency-control max-sessions="1" expired-url=/login?expired=true" session-registry-alias="sessionRegistry"/>
</session-management>
<form-login
login-page="/login"
default-target-url="/"
always-use-default-target="true"
authentication-failure-url="/login?error=true"/>
<logout logout-success-url="/login" invalidate-session="true" delete-cookies="JSESSIONID"/>
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="SELECT id AS username, password, enabled FROM users WHERE id=?;"
authorities-by-username-query="SELECT id AS username, role FROM users WHERE id=?;"
role-prefix="ROLE_"/>
<password-encoder hash="md5">
<salt-source ???/>
</password-encoder>
</authentication-provider>
</authentication-manager>
これは、 web.xmlファイルからの関連する抜粋です。
<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>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
これは、 application-context.xmlファイルからの関連する抜粋です。
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<beans:property name="driverClass" value="org.postgresql.Driver"/>
<beans:property name="url" value="jdbc:postgresql://host:port/database"/>
<beans:property name="username" value="username"/>
<beans:property name="password" value="password"/>
</beans:bean>
実装に関しては、これが唯一の関連するコントローラーLoginController.javaです(他のすべてのコントローラーは、アプリによって提供される実際の機能を処理します)。
@Controller
public class LoginController {
private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
/**
* Displays the Login form.
*/
@RequestMapping(value="/login", method=RequestMethod.GET)
public String displayLoginForm(@RequestParam(value="error", required=false) String error, @RequestParam(value="expired", required=false) String expired, Model model) {
LOGGER.info("Displaying Login form:: displayLoginForm(Model)");
if (error != null) {
LOGGER.info("Invalid username or password.");
model.addAttribute("error", "Invalid username or password.");
}
if (expired != null) {
LOGGER.info("Session has been expired (possibly due to multiple concurrent logins being attempted as the same user)");
model.addAttribute("expired", "Session has been expired (possibly due to multiple concurrent logins being attempted as the same user).");
}
return "login";
}}
どんなポインタでも大歓迎です。お時間とご協力をいただき、ありがとうございました。
編集:ドキュメント
を読んで理解したところ、これはデータベースに保存されているユーザーのパスワードであるため、
試してみました。しかし、うまくいきません。ログインしようとするたびに、資格情報が無効であるというメッセージが表示されます。ただし、資格情報は実際には有効です。
<password-encoder hash="md5">
<salt-source user-property="password"/>
</password-encoder>
おそらく、このページのハッシュと認証セクションで説明されているイベントのいずれかが、機能していない理由である可能性があります。提案どおりに適切なテストを作成する方法を考えています。
別の編集:
テストとして、password-encoder 要素をコメントアウトし、プレーン テキストのパスワードで認証を試みました (つまり、テスト ユーザーを作成し、プレーン テキストのパスワードをデータベースに保存しました)。出来た。したがって、Spring Security がユーザーが入力したパスワードをエンコードする方法に問題があることは間違いありません。これは、データベースに格納されているハッシュ化されたパスワードと一致しません。