[解決済み】Spring経由のRESTful認証
質問
問題あり。
私たちは、機密情報を含むSpring MVCベースのRESTful APIを持っています。APIは安全であるべきですが、各リクエストでユーザーの認証情報(ユーザー/パスのコンボ)を送信することは望ましくありません。RESTのガイドライン(および社内のビジネス要件)により、サーバーはステートレスのままでなければなりません。APIはマッシュアップ方式で他のサーバーから消費される。
要求事項
-
クライアントが
.../authenticate
(保護されていない URL) に認証情報を入力すると、サーバーは安全なトークンを返します。このトークンには、サーバーが今後のリクエストを検証し、ステートレスを維持するのに十分な情報が含まれています。これはおそらく、Spring Securityの リメンバーミートークン . -
クライアントは、様々な(保護された)URLに対して、前回取得したトークンをクエリパラメータ(または、あまり望ましくないが、HTTPリクエストヘッダ)として付加して、以降リクエストを行う。
-
クライアントがクッキーを保存することは期待できない。
-
私たちはすでにSpringを使用しているので、ソリューションはSpring Securityを使用する必要があります。
この問題を解決するために、私たちは壁に頭を打ち付けています。
上記のシナリオを想定した場合、この特殊なニーズをどのように解決しますか?
どのように解決するのか?
OPに書かれているとおりに動作させることができました。以下は、私たちが行ったことです。
セキュリティコンテキストをこのように設定します。
<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="CustomAuthenticationEntryPoint">
<security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" />
<security:intercept-url pattern="/authenticate" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>
<bean id="CustomAuthenticationEntryPoint"
class="com.demo.api.support.spring.CustomAuthenticationEntryPoint" />
<bean id="authenticationTokenProcessingFilter"
class="com.demo.api.support.spring.AuthenticationTokenProcessingFilter" >
<constructor-arg ref="authenticationManager" />
</bean>
ご覧のように、カスタムの
AuthenticationEntryPoint
を返すだけで、基本的には
401 Unauthorized
もしリクエストがフィルタチェーンの中で
AuthenticationTokenProcessingFilter
.
CustomAuthenticationEntryPoint :
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
}
}
AuthenticationTokenProcessingFilter :
public class AuthenticationTokenProcessingFilter extends GenericFilterBean {
@Autowired UserService userService;
@Autowired TokenUtils tokenUtils;
AuthenticationManager authManager;
public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
this.authManager = authManager;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
@SuppressWarnings("unchecked")
Map<String, String[]> parms = request.getParameterMap();
if(parms.containsKey("token")) {
String token = parms.get("token")[0]; // grab the first "token" parameter
// validate the token
if (tokenUtils.validate(token)) {
// determine the user based on the (already validated) token
UserDetails userDetails = tokenUtils.getUserFromToken(token);
// build an Authentication object with the user's info
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));
// set the authentication into the SecurityContext
SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication));
}
}
// continue thru the filter chain
chain.doFilter(request, response);
}
}
明らかに
TokenUtils
には非公開の(そして非常にケース・スペシフィックな)コードが含まれており、簡単に共有することはできません。以下はそのインターフェイスです。
public interface TokenUtils {
String getToken(UserDetails userDetails);
String getToken(UserDetails userDetails, Long expiration);
boolean validate(String token);
UserDetails getUserFromToken(String token);
}
これで、いいスタートが切れるはずだ。
関連
-
[解決済み] maven. -source 1.5ではラムダ式がサポートされていません。
-
[解決済み] Jdbctemplate の文字列に対するクエリです。EmptyResultDataAccessException: 不正な結果サイズ:期待値1、実際0
-
[解決済み] XX:MaxDirectMemorySizeの既定値
-
[解決済み] java.util.concurrent.ExecutionException 例外をどのように処理しますか?
-
[解決済み] publicId と systemId の間に空白が必要です。
-
[解決済み] IntegerからBigIntegerへの変換
-
[解決済み] RESTful WebServiceにファイルや関連データをJSONで投稿する。
-
[解決済み] RESTアプリケーションはステートレスであることが前提である場合、セッションはどのように管理するのですか?
-
[解決済み】RESTful 認証
-
[解決済み】セッションは本当にRESTfulnessに違反するのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JVMフラグCMSClassUnloadingEnabledは、実際に何をするのですか?
-
[解決済み] Cloneable throws CloneNotSupportedException
-
[解決済み] android.support.v4.app.FragmentActivity' で 'TAG' がプライベートアクセスされている。
-
[解決済み] Java UnknownFormatConversionException
-
[解決済み] Java Swingで複数のボタンに対して複数のActionListenersを追加する方法
-
[解決済み] javascriptでExpression言語を使うには?
-
[解決済み] JAVA_OPTIONS、JAVA_TOOL_OPTIONS、JAVA_OPTSの違いについて
-
[解決済み] アニメーションGIFの表示
-
[解決済み] java.io.IOException。DER長の短い読み取り
-
[解決済み] .lengthが解決できない、またはフィールドでない