役割または権限に基づくアクセス制御
- hasAuthorityメソッド
現在のプリンシパルに指定された権限がある場合はtrueを返し、そうでない場合はfalseを返します。- 構成クラスで現在のアクセスアドレスを設定するために使用できるアクセス許可
//当前登录用户,只要具有admin权限才可以访问这个路径 .antMatchers("/test/index").hasAuthority("admin")
- UserDetailsServiceで、返されたUserオブジェクトにアクセス許可を設定します
List<GrantedAuthority> role = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
- type = Forbidden、status = 403はアクセスがないことを意味します
現在のプリンシパルに提供された役割のいずれかがある場合、hasAnyAuthorityメソッドはtrueを返します
.antMatchers("/test/index").hasAnyAuthority("admin,manager")
List<GrantedAuthority> role = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
- hasRoleメソッド
- 役割を割り当てるときは、接頭辞「ROLE_」を追加する必要があります
.antMatchers("/test/index").hasRole("sale")
List<GrantedAuthority> role = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_sale");
private static String hasRole(String role) {
Assert.notNull(role, "role cannot be null");
Assert.isTrue(!role.startsWith("ROLE_"), () -> {
return "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'";
});
return "hasRole('ROLE_" + role + "')";
}
- hasAnyRoleメソッド
ユーザーはそれらのいずれかにアクセスできます
カスタム403ページ
http.exceptionHandling().accessDeniedPage("/unauth.html");
認証と承認の注釈の使用
- @Securedアノテーション、ユーザーには特定の役割があり、メソッドにアクセスできます
- スタートアップクラス(構成クラス)オープンアノテーション
@EnableGlobalMethodSecurity(securedEnabled = true)
- Controllerメソッドのアノテーションを使用して役割を設定します
@GetMapping("/secured") @Secured({ "ROLE_sale","ROLE_manager"}) public String secured(){ return "hello secured"; }
- userDetailsServiceはユーザーロールを設定します
List<GrantedAuthority> role = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_sale");
- @PreAuthorize:メソッドが実行される前に確認してください
- 注釈を開く
@EnableGlobalMethodSecurity(prePostEnabled = true)
- コントローラメソッドでアノテーションを使用する
@GetMapping("/preAuthorize") @PreAuthorize("hasAnyAuthority('admin,manager')") public String preAuthorize(){ return "hello PreAuthorize"; }
- @PostAuthorize:メソッドの実行後に確認します
- @PostFilter:メソッドによって返されたデータをフィルタリングします
@GetMapping("/testFilter")
@PreAuthorize("hasAnyAuthority('admin,manager')")
@PostFilter("filterObject.username == 'admin11'")
public List<User> testFilter(){
ArrayList<User> list = new ArrayList<>();
list.add(new User(11,"admin11","111"));
list.add(new User(22,"admin22","222"));
System.out.println(list);
return list;
}
コンソール出力
[User(id=11, username=admin11, password=111), User(id=22, username=admin22, password=222)]
フロントエンド出力
[
{
id: 11,
username: "admin11",
password: "111"
}
]
- @PreFilter:コントローラーに入る前にデータをフィルター処理する
ユーザーのログアウト
- 構成クラスに出口構成を追加します
http.logout().logoutUrl("/logout")
.logoutSuccessUrl("/test/hello").permitAll();
- テスト
- 構成クラスを変更し、ログインに成功したら成功ページにジャンプします
- 成功ページにハイパーリンクを追加し、終了パスを記述します
- ログインが成功したら、成功ページをクリックしてログアウトし、他のコントローラーにアクセスしてアクセスできません。
自動ログイン
- 実現原理
- 実装
- データベーステーブルを作成する
- 構成クラスを変更し、データソースを挿入します
//注入数据源 @Autowired private DataSource dataSource; //配置对象 @Bean public PersistentTokenRepository persistentTokenRepository(){ JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); jdbcTokenRepository.setDataSource(dataSource); jdbcTokenRepository.setCreateTableOnStartup(true); return jdbcTokenRepository; }
- 構成クラスで自動ログインを構成する
.rememberMe().tokenRepository(persistentTokenRepository()) .tokenValiditySeconds(60)
- ログインページにチェックボックスを追加
<input type="checkbox" name="remember-me">自动登录
- データベースに保存されている情報
CSRF:クロスサイトリクエストフォージェリ
-
原理
-
デフォルトはオン
-
PATCH、POST、PUT、DELETEの場合
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
- GET、HEAD、TRACE、OPTIONSは保護されていません