在〈自訂登入登出頁面〉只使用了 authenticated
方法,這表示只要是登入成功,就可以在 Web 應用程式中暢行無阻,然而,Web 應用程式中也許某些頁面只允許站長存取,有些資源只允許會員使用呢?
可以使用 hasRole
或 hasAnyRole
等方法,指定某些頁面可以存取的角色,例如,目前 SecurityConfig
中有 ADMIN
與 ROLE
兩種角色,就用這兩個角色來玩點權限設定吧!
package cc.openhome.web;
... 略
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder pwdEncoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(pwdEncoder)
.withUser("admin")
.password(pwdEncoder.encode("admin12345678"))
.roles("ADMIN", "MEMBER")
.and()
.withUser("caterpillar")
.password(pwdEncoder.encode("12345678"))
.roles("MEMBER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/member").hasAnyRole("ADMIN", "MEMBER")
.antMatchers("/user").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login_page")
.loginProcessingUrl("/perform_login")
.failureUrl("/login_page?error")
.and()
.logout()
.logoutUrl("/perform_logout")
.logoutSuccessUrl("/login_page?logout");
}
}
如上設定之後,登入的使用者必須有 ADMIN
角色才可以存取 /admin
,而 MEMBER
角色才可以存取 /member
,/user
只需要登入就可以看,至於就沒有限制。
如果登入為 caterpillar
,卻想要觀看 /admin
的話,就會出現 403 – Forbidden 的頁面。
roles
方法設定的角色名稱,實際上都會被加上 ROLE_
前置名稱,在設定授權時,使用 hasAuthority
或 hasAyAuthority
方法,就必須使用 ROLE_XXX
。例如:
... 略
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin").hasAuthority("ROLE_ADMIN")
.antMatchers("/member").hasAuthority("ROLE_MEMBER")
.antMatchers("/user").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login_page")
.loginProcessingUrl("/perform_login")
.failureUrl("/login_page?error")
.and()
.logout()
.logoutUrl("/perform_logout")
.logoutSuccessUrl("/login_page?logout");
}
... 略
你也可以使用 access
指定 Spring EL,實現更靈活的配置,例如:
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin").access("hasRole('ADMIN') and hasIpAddress('192.168.8.100')")
.antMatchers("/member").access("hasAnyRole('ADMIN', 'MEMBER')")
.antMatchers("/user").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login_page")
.loginProcessingUrl("/perform_login")
.failureUrl("/login_page?error")
.and()
.logout()
.logoutUrl("/perform_logout")
.logoutSuccessUrl("/login_page?logout");
}
...
有關於 access
與 Spring EL 的搭配,可以參考〈Expression-Based Access Control〉。
你可以在 RoleAuthorization 找到以上的範例專案。