SpringSecurity請求授權(quán)規(guī)則配置與注解詳解
1、請求授權(quán)規(guī)則配置
這里主要是重寫WebSecurityConfigurerAdapter 的configure方法。
protected void configure(HttpSecurity http) throws Exception {
this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.
authorizeRequests()
.anyRequest())
.authenticated()
.and())
.formLogin()
.and())
.httpBasic();
}
① 自定義登錄
這里UsernamePasswordAuthenticationFilter 將起作用。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login.html") //登錄頁面
.loginProcessingUrl("/user/login") // 默認(rèn)處理登錄的請求
.successForwardUrl("/success") //登錄成功后跳轉(zhuǎn)到哪個(gè)URL
.defaultSuccessUrl("/index",true)// 登錄成功后跳轉(zhuǎn)路徑
.failureForwardUrl("/fail") //登錄失敗后跳轉(zhuǎn)到哪個(gè)URL
.permitAll();
}
這里successForwardUrl與defaultSuccessUrl 都可以實(shí)現(xiàn)認(rèn)證成功后跳轉(zhuǎn)的效果,不過具體用法上有所區(qū)別。通常建議使用defaultSuccessUrl,至于具體區(qū)別后面另開章節(jié)學(xué)習(xí)。
還可以修改用戶名和密碼的key(默認(rèn)是username 和password):
.usernameParameter("userName") //自定義獲取用戶登錄名
.passwordParameter("password") //自定義獲取用戶登錄密碼
② 設(shè)置放行與需要認(rèn)證的請求
http.authorizeRequests()
.antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
.permitAll()//匹配上述請求的直接放行
.anyRequest().authenticated();//其他請求都需要認(rèn)證
③ 基于角色或權(quán)限進(jìn)行訪問控制
回顧上文我們自定義實(shí)現(xiàn)類設(shè)置用戶角色權(quán)限如下:

這里用戶角色、權(quán)限是指定的,那么我們是不是可以升級一下從數(shù)據(jù)庫查詢呢?如下圖所示:

hasAuthority 方法
如果當(dāng)前的主體具有指定的權(quán)限,則返回 true,否則返回false。
http.authorizeRequests()
.antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
.permitAll()
.antMatchers("/findAll").hasAuthority("admin") // 用戶訪問findAll 必須有 admin 權(quán)限
.anyRequest().authenticated();//其他請求都需要認(rèn)證
hasAnyAuthority方法
如果當(dāng)前的主體有任何提供的角色(給定的作為一個(gè)逗號(hào)分隔的字符串列表)的話,返回true。
http.authorizeRequests()
.antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
.permitAll()
.antMatchers("/findAll").hasAuthority("admin") // 用戶訪問findAll 必須有 admin 權(quán)限
.antMatchers("/find").hasAnyAuthority("admin","sale") // 用戶訪問 find ,擁有admin或者sale之一即可
.anyRequest().authenticated();//其他請求都需要認(rèn)證
hasRole 方法
如果用戶具備給定角色就允許訪問,否則出現(xiàn)403。如果當(dāng)前主體具有指定的角色,則返回true。
這里需要說明的是在SpringSecurity源碼中對hasRole 進(jìn)行了處理,為角色名自動(dòng)添加上了ROLE_前綴。故我們配置的時(shí)候不加該前綴即可。
org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer#hasRole

http.authorizeRequests()
.antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
.permitAll()
.antMatchers("/findAll").hasAuthority("admin") // 用戶訪問findAll 必須有 admin 權(quán)限
.antMatchers("/find").hasAnyAuthority("admin","sale") // 用戶訪問 find ,擁有admin或者sale之一即可
.antMatchers("/sale/**").hasRole("sale") // 需要用戶具有sale角色
.anyRequest().authenticated();//其他請求都需要認(rèn)證
hasAnyRole方法
表示用戶具備任何一個(gè)條件都可以訪問。
http.authorizeRequests()
.antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
.permitAll()
.antMatchers("/findAll").hasAuthority("admin") // 用戶訪問findAll 必須有 admin 權(quán)限
.antMatchers("/find").hasAnyAuthority("admin","sale") // 用戶訪問 find ,擁有admin或者sale之一即可
.antMatchers("/sale/**").hasRole("sale") // 需要用戶具有sale角色
.antMatchers("/product/**").hasAnyRole("admin","product") //用戶具有admin或者product角色之一即可
.anyRequest().authenticated();//其他請求都需要認(rèn)證
④ 自定義403訪問拒絕頁面
修改配置類
http.exceptionHandling().accessDeniedPage("/unauth.html");
這里需要說明的是你的靜態(tài)資源文件路徑下比如static下需要有unauth.html頁面,當(dāng)然這里也可以換成一個(gè)請求如/unauth,編寫controller來處理該請求。
⑤ 自定義退出
修改配置類如下:
http.logout().logoutUrl("/logout") //退出登錄請求
.logoutSuccessUrl("/index") //注銷成功后跳轉(zhuǎn)地址
.permitAll();
還可以指定在退出時(shí)刪除某些cookie、注銷會(huì)話:
.deleteCookies("remember-me","sign")
.invalidateHttpSession(true)
2、SpringSecurity的注解
通過方法上的注解我們可以實(shí)現(xiàn)在后端服務(wù)上細(xì)粒度的權(quán)限校驗(yàn)。
主啟動(dòng)類上要添加@EnableGlobalMethodSecurity注解
@SpringBootApplication
@MapperScan("com.jane.mapper")
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled = true)
public class Securitydemo1Application {
public static void main(String[] args) {
SpringApplication.run(Securitydemo1Application.class, args);
}
}
① @Secured
判斷是否具有角色,另外需要注意的是這里匹配的字符串需要添加前綴“ROLE_“ 。使用該注解前要先開啟注解支持:@EnableGlobalMethodSecurity(securedEnabled=true)
// 測試注解:
@RequestMapping("testSecured")
@ResponseBody
@Secured({"ROLE_normal","ROLE_admin"})
public String helloUser() {
return "hello,user";
}
② @PreAuthorize
先開啟注解功能: @EnableGlobalMethodSecurity(prePostEnabled = true)。
@PreAuthorize注解適合進(jìn)入方法前的權(quán)限驗(yàn)證,是一種常見的應(yīng)用策略。
@RequestMapping("/preAuthorize")
@ResponseBody
//@PreAuthorize("hasRole('ROLE_admin')")
@PreAuthorize("hasAnyAuthority('menu:system')")
public String preAuthorize(){
System.out.println("preAuthorize");
return "preAuthorize";
}
可以看到這里權(quán)限表達(dá)式中可以使用hasRole、hasAnyRole、hasAuthority 以及hasAnyAuthority來靈活控制。
③ @PostAuthorize
先開啟注解功能: @EnableGlobalMethodSecurity(prePostEnabled = true) 。@PostAuthorize 注解很少使用,在方法執(zhí)行后再進(jìn)行權(quán)限驗(yàn)證,適合驗(yàn)證帶有返回值的權(quán)限。
@RequestMapping("/testPostAuthorize")
@ResponseBody
@PostAuthorize("hasAnyAuthority('menu:system')")
public String preAuthorize(){
System.out.println("test--PostAuthorize");
return "PostAuthorize";
}
④ @PostFilter
@PostFilter :權(quán)限驗(yàn)證之后對數(shù)據(jù)進(jìn)行過濾。表達(dá)式中的 filterObject 引用的是方法返回值List中的某一個(gè)元素。通常也很少使用。
如下留下用戶名是admin1的數(shù)據(jù):
@RequestMapping("getAll")
@PreAuthorize("hasRole('ROLE_admin')")
@PostFilter("filterObject.username == 'admin1'")
@ResponseBody public List<UserInfo> getAllUser(){
ArrayList<UserInfo> list = new ArrayList<>();
list.add(new UserInfo(1l,"admin1","6666"));
list.add(new UserInfo(2l,"admin2","888"));
return list;
}
⑤ @PreFilter
@PreFilter: 進(jìn)入控制器之前對數(shù)據(jù)進(jìn)行過濾。
@RequestMapping("getTestPreFilter")
@PreAuthorize("hasRole('ROLE_admin')")
@PreFilter(value = "filterObject.id%2==0")
@ResponseBody public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> list){
list.forEach(t-> { System.out.println(t.getId()+"\t"+t.getUsername()); });
return list;
}
綜上,這里我們常使用@Secured與@PreAuthorize兩個(gè)注解在進(jìn)入方法前進(jìn)行角色、權(quán)限的控制。
進(jìn)入方法前數(shù)據(jù)的過濾@PreFilter注解偶爾會(huì)看到,至于方法執(zhí)行完后進(jìn)行校驗(yàn)的兩個(gè)注解@PostAuthorize與@PostFilter幾乎不用。
到此這篇關(guān)于SpringSecurity請求授權(quán)規(guī)則配置與注解詳解的文章就介紹到這了,更多相關(guān)SpringSecurity配置與注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用?Spire.PDF?for?Java輕松搞定拆分PDF
有時(shí)我們需要對大型?PDF?文檔進(jìn)行精細(xì)化管理,例如,將一個(gè)多頁的合同拆分成單頁以便逐頁審批,本文將為您介紹如何使用?Spire.PDF?for?Java?庫來輕松實(shí)現(xiàn)?PDF?拆分,感興趣的小伙伴可以了解下2025-12-12
Java 獲取當(dāng)前系統(tǒng)時(shí)間的三種方法
這篇文章主要介紹了Java 獲取當(dāng)前系統(tǒng)時(shí)間的三種方法,幫助大家利用Java處理時(shí)間,感興趣的朋友可以了解下2020-10-10
Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室
這篇文章主要介紹了Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Java中實(shí)現(xiàn)訂單超時(shí)自動(dòng)取消功能(最新推薦)
本文介紹了Java中實(shí)現(xiàn)訂單超時(shí)自動(dòng)取消功能的幾種方法,包括定時(shí)任務(wù)、JDK延遲隊(duì)列、Redis過期監(jiān)聽、Redisson分布式延遲隊(duì)列、RocketMQ延遲消息和RabbitMQ死信隊(duì)列,每種方法都有其優(yōu)缺點(diǎn),可以根據(jù)具體需求選擇合適的方法,感興趣的朋友一起看看吧2025-02-02
java實(shí)現(xiàn)在SSM下使用支付寶掃碼支付功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)在SSM下使用支付寶掃碼支付功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
Java?Spring?boot日期和時(shí)間統(tǒng)一設(shè)置三種方法
時(shí)間和日期的統(tǒng)一設(shè)置在項(xiàng)目中經(jīng)常是會(huì)遇到的,下面這篇文章主要給大家介紹了關(guān)于Java?Spring?boot日期和時(shí)間統(tǒng)一設(shè)置的三種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08
Java通過接口實(shí)現(xiàn)匿名類的實(shí)例代碼
這篇文章介紹了Java通過接口實(shí)現(xiàn)匿名類的實(shí)例代碼,有需要的朋友可以參考一下2013-10-10
JDBC使用游標(biāo)實(shí)現(xiàn)分頁查詢的方法
這篇文章主要介紹了JDBC使用游標(biāo)實(shí)現(xiàn)分頁查詢的方法,實(shí)例分析了jdbc查詢過程中游標(biāo)的使用及查詢分頁相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-08-08

