1.spring security 過濾器鏈
spring security中的除了用戶登錄校驗相關的過濾器,最后還包含了鑒權功能的過濾器,還有匿名資源訪問的過濾器鏈,相關的圖解如下:
2.控制授權的相關類
這里是整個spring security的過濾器鏈中的授權流程中控制權限的類的相關圖示:
這里主要是從AccessDecisionVoter的投票者(譯稱)把信息傳遞給投票管理者AccessDecisionManager,最終來判斷是過還是不過(也就是有沒有權限).有兩種可能的類:
1.不管有多少請求投票不過,只要有一個過就可以通過(UnanimousBased);
2.不管有多少請求投票通過,只要有一個不通過就不讓通過(AffirmativeBased);
3.比較投通過和不通過的個數,誰多久就按照誰的方式來(Consensusbased).
這里可以可能聽起來有點繞,但實際上就是三種控制權限的方式類,我們可以認為Spring security已經幫我們做好了最終的判斷,我們只需要當一個旁觀者即可.
我們再來關注SecurityContextHolder這個類,他會將我們的權限信息封裝到Authentication中,SecurityConfig則是相關的Spring security的配置信息,這個類會將相關的信息傳遞到ConfigAttribute中.
3.配置簡單的權限
這個在身份信息固定,並且不會經常變動的情況下可以按照如下配置,否則不建議這么做,這里只適用於簡單的場景.
MyUserDetailsService:
private SocialUserDetails buildUser(String userId) {
// 根據用戶名查找用戶信息
//根據查找到的用戶信息判斷用戶是否被凍結
/**
* 可以從數據庫查出來用戶名和密碼進行比對,為了方便我這里就直接固定了
*/
String password = passwordEncoder.encode("123456");
logger.info("數據庫密碼是:"+password);
//注意這里配置角色的時候需要加ROLE_前綴
return new SocialUser(userId, password,
true, true, true, true,
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
}
BrowserSecurityConfig:
//這里是硬編碼權限 只限於簡單的用戶權限 這里的角色名稱嚴格區分大小寫
//這里可以指定HttpMethod 如HttpMethod.GET,
.antMatchers("/user/**").hasRole("ADMIN")
.anyRequest() //所有請求
.authenticated() //都需身份認證
4.權限表達式
之前我們一直都有用到權限表達式,比如最常用的permitAll和Authenticated,這個權限表達式就是允許所有都能訪問的意思,其他的相關的權限表達式如下所示:
這里可以改寫權限的表達如下:
.antMatchers("/user/**").access("hasRole('ADMIN') and hasIpAddress('XXXXXX')")
.anyRequest() //所有請求
.authenticated() //都需身份認證
5.spring security控制授權代碼封裝
代碼相關:
AuthorizeConfigProvider:
/**
* 這個是授權的類
*/
public interface AuthorizeConfigProvider {
void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
}
CityAuthorizeConfigProvider:
//配置permitAll的路徑
@Component
public class CityAuthorizeConfigProvider implements AuthorizeConfigProvider {
@Autowired
private SecurityProperties securityProperties;
@Override
public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
config.antMatchers(
"/static/**","/page/login","/page/failure","/page/mobilePage",
"/code/image","/code/sms","/authentication/mobile",securityProperties.getBrower().getSignUPUrl(),
"/user/register","/page/registerPage","/page/invalidSession","/page/logoutSuccess",securityProperties.getBrower().getSignOutUrl()
)
.permitAll();
}
}
AuthorizeConfigManager:
/**
* AuthorizeConfigManager
*/
public interface AuthorizeConfigManager {
void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config);
}
CityAuthorizeConfigManager:
@Component
public class CityAuthorizeConfigManager implements AuthorizeConfigManager {
@Autowired
private Set<AuthorizeConfigProvider> authorizeConfigProviders;
@Override
public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
for (AuthorizeConfigProvider authorizeConfigProvider : authorizeConfigProviders) {
authorizeConfigProvider.config(config);
}
//除了自己配置的CityAuthorizeConfigProvider的內容外 其他的都需要認證
config.anyRequest().authenticated();
}
}
在user中我們可以配置訪問的頁面權限:
DemoAuthorizeConifgProvider:
@Component
public class DemoAuthorizeConifgProvider implements AuthorizeConfigProvider {
@Override
public void config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
config.antMatchers("/demo.html","/user/**")
.hasRole("ADMIN");
}
}
注意在BrowserSecurityConfig中注釋掉相關的代碼后需要加入如下代碼:
@Autowired
private AuthorizeConfigManager authorizeConfigManager;
在configure方法中調用:
authorizeConfigManager.config(http.authorizeRequests());
配置完后我們登陸進來,訪問http://localhost:8060/demo.html 顯示403權限拒絕,這個就說明權限生效了
4.項目git地址
(喜歡記得點星支持哦,謝謝!)