Spring Securityのロールベースのアクセス認可の例
今日はスプリングセキュリティのロールベースのアクセスと認可の例を見ていきます。ただし、この投稿を読む前に、私の以前の投稿「Spring 4 Security MVC ログインログアウトの例」をご覧ください。それにより、Spring 4 Securityに関する基本的な知識を得ることができます。
スプリングセキュリティの役割
この投稿では、SpringのWebアプリケーションにおいて「USER」や「ADMIN」といったSpringセキュリティのロールをどのように定義し、使用し、管理するかについて話し合います。この投稿の例も、以前の投稿と同様に、Spring 4 MVC SecurityのインメモリストアとSpring Java Configuration機能を使用してアプリケーションを開発しています。つまり、web.xmlファイルを使用せず、Spring XML構成の一行も記述しません。私たちは「インメモリストア」オプションを使用してユーザーの資格情報を保存・管理します。この例の開発には、Spring 4.0.2.RELEASE、Spring STS 3.7 Suite IDE、Spring TC Server 3.1、Java 1.8、およびMavenビルドツールを使用します。
スプリングセキュリティの役割ベースのアクセス認可の例
-
- 以下の詳細を持つ「Simple Spring Web Maven」プロジェクトをSpring STS Suiteで作成してください。
- プロジェクト名:SpringMVCSecruityMavenRolesApp2。以前の投稿で使用したpom.xmlファイルをそのまま使用し、以下の変更を加えます。
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>
<build>
<finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
-
- 私の前の投稿から、すべてのJavaとJSPファイルを使用してください。ここでは、更新されたものまたは新たに追加されたコンテンツのみを議論します。
- LoginSecurityConfig.javaファイルをアップデートして、「USER」と「ADMIN」というユーザーロールを設定してください。
package com.scdev.spring.secuity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.inMemoryAuthentication()
.withUser("jduser").password("jdu@123").authorities("ROLE_USER")
.and()
.withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
コードの説明
-
- configureGlobal()メソッドでは、2つのユーザーを追加しました。1つのユーザーは「ROLE_USER」の役割を持ち、もう1つのユーザーは「ROLE_USER」と「ROLE_ADMIN」の両方の役割を持っています。つまり、この2番目のユーザーは管理者ユーザーとして機能します。このようにして、私たちは任意の数のユーザーと役割を設定することができます。
-
- アプリケーションでの役割を設定するには、authorities(ROLE)またはroles(ROLE)メソッドのどちらかを使用することができます。
- authorities()メソッドとroles()メソッドの違い:
- authorities() needs complete role name like “ROLE_USER”
- roles() needs role name like “USER”. It will automatically adds “ROLE_” value to this “USER” role name.
- configure()メソッドで、必要なアクセス権限を持つ異なるURLを定義しました。
antMatchers("/homePage")
.access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
このコードスニペットは、「/homePage」がUSERとADMINの両方の役割で利用可能であることを設定します。
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
このコードスニペットは、”/userPage”は「USER」の役割のみがアクセスできるように設定し、また “/adminPage”は「ADMIN」の役割のみがアクセスできるように設定しています。他の役割がこれらのページにアクセスした場合、”403 アクセスが拒否されました”というエラーメッセージが表示されます。
- 以下のように新しいURLアクセスパスを定義するために、LoginController.javaコントローラーファイルを更新してください。
package com.scdev.spring.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class LoginController {
@RequestMapping(value = { "/"}, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.setViewName("welcomePage");
return model;
}
@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
public ModelAndView homePage() {
ModelAndView model = new ModelAndView();
model.setViewName("homePage");
return model;
}
@RequestMapping(value = {"/userPage"}, method = RequestMethod.GET)
public ModelAndView userPage() {
ModelAndView model = new ModelAndView();
model.setViewName("userPage");
return model;
}
@RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.setViewName("adminPage");
return model;
}
@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid Credentials provided.");
}
if (logout != null) {
model.addObject("message", "Logged out from JournalDEV successfully.");
}
model.setViewName("loginPage");
return model;
}
}
前回の投稿例に加えて、ここに2つの新しいURLを追加しました。
-
- 「/userPage」はUSERロールが通常のユーザー活動をアクセスして実行するために使用されます。
「/adminPage」はADMINロールが管理ユーザーの活動をアクセスして実行するために使用されます。また、ADMINロールは「/userPage」のURLにもアクセスすることができます。
homePage.jspファイルを更新して、ユーザーと管理ユーザーの役割に特定の活動を提供します。
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Logout</a>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
<li>Java 8 tutorial</li>
<li>Spring tutorial</li>
<li>Gradle tutorial</li>
<li>BigData tutorial</li>
</ul>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
ここでは、トップフレームに3つのメニューオプションを追加しました。”ログアウト”については、以前の投稿で既に説明しました。新たな2つのリンクは以下です:
-
- JDユーザー:「ユーザー」と「管理者」の両方がアクセスできます。
- JD管理者:アクセスは「管理者」の役割のみ可能です。
リアルタイムアプリケーションでは、「JD User」リンクのみを「USER」役割に表示し、「JD Admin」リンクを非表示にします。このリンクが「USER」役割によってアクセス可能かどうかや、正確なエラーメッセージを確認するために、このリンクは非表示にしていません。20. 「ADMIN」の役割のホームページとして機能する新しいadminPage.jspファイルを追加してください。
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>Admin Page</h3>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
- 「USER」の役割用のホームページとして、新しいuserPage.jspファイルを追加してください。
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>User Page</h3>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
私たちはアプリケーション開発を終了しました。今はプロジェクトの最終構造を見て、アプリケーションのテストを行う時です。26. 最終プロジェクトの構造は以下のようになります。
春のセキュリティの役割の例となるアプリケーションのテスト
-
- Spring STS IDEのプロジェクトを右クリックし、「実行」→「サーバー上で実行」を選択します。
-
- 以下のように表示されるデフォルトのアプリケーションのウェルカムページにアクセスします: 3. 「JournalDEVにログイン」リンクをクリックします。ログインページに移動します。
-
- 5. 最初に「USER」の権限情報を使用してログインします:
-
- ユーザー名: jduser パスワード: jdu@123 これでアプリケーションのホームページが表示され、3つのメニューオプション「JD User」、「JD Admin」、「ログアウト」があります。 「JD User」リンクをクリックします。今回は「USER」の権限情報でログインしているため、以下のようにこのリンクにアクセスできます。 Spring STS IDEで戻る矢印を使用して、今度は「JD Admin」リンクをクリックします。 「USER」の権限情報でログインしているため、このリンクにアクセスできません。そのため、次のエラーメッセージが表示されます:「403 アクセスが拒否されました」。
-
- 9. 今度は「ADMIN」の権限情報でログインしてみてください。
- ユーザー名: jdadmin パスワード: jda@123 この時点で「JD Admin」リンクに正常にアクセスできるようになるはずです。 「ログアウト」リンクをテストしてアプリケーションからログアウトしてみてください。
これは、Webアプリケーションのページに認可されたアクセスを提供するためのSpringセキュリティの役割の例についてのすべてです。