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") // 默認處理登錄的請求 .successForwardUrl("/success") //登錄成功后跳轉(zhuǎn)到哪個URL .defaultSuccessUrl("/index",true)// 登錄成功后跳轉(zhuǎn)路徑 .failureForwardUrl("/fail") //登錄失敗后跳轉(zhuǎn)到哪個URL .permitAll(); }
這里successForwardUrl與defaultSuccessUrl 都可以實現(xiàn)認證成功后跳轉(zhuǎn)的效果,不過具體用法上有所區(qū)別。通常建議使用defaultSuccessUrl,至于具體區(qū)別后面另開章節(jié)學習。
還可以修改用戶名和密碼的key(默認是username 和password):
.usernameParameter("userName") //自定義獲取用戶登錄名 .passwordParameter("password") //自定義獲取用戶登錄密碼
② 設(shè)置放行與需要認證的請求
http.authorizeRequests() .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行 .permitAll()//匹配上述請求的直接放行 .anyRequest().authenticated();//其他請求都需要認證
③ 基于角色或權(quán)限進行訪問控制
回顧上文我們自定義實現(xiàn)類設(shè)置用戶角色權(quán)限如下:
這里用戶角色、權(quán)限是指定的,那么我們是不是可以升級一下從數(shù)據(jù)庫查詢呢?如下圖所示:
hasAuthority 方法
如果當前的主體具有指定的權(quán)限,則返回 true,否則返回false。
http.authorizeRequests() .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行 .permitAll() .antMatchers("/findAll").hasAuthority("admin") // 用戶訪問findAll 必須有 admin 權(quán)限 .anyRequest().authenticated();//其他請求都需要認證
hasAnyAuthority方法
如果當前的主體有任何提供的角色(給定的作為一個逗號分隔的字符串列表)的話,返回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();//其他請求都需要認證
hasRole 方法
如果用戶具備給定角色就允許訪問,否則出現(xiàn)403。如果當前主體具有指定的角色,則返回true。
這里需要說明的是在SpringSecurity源碼中對hasRole 進行了處理,為角色名自動添加上了ROLE_前綴。故我們配置的時候不加該前綴即可。
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();//其他請求都需要認證
hasAnyRole方法
表示用戶具備任何一個條件都可以訪問。
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();//其他請求都需要認證
④ 自定義403訪問拒絕頁面
修改配置類
http.exceptionHandling().accessDeniedPage("/unauth.html");
這里需要說明的是你的靜態(tài)資源文件路徑下比如static下需要有unauth.html頁面,當然這里也可以換成一個請求如/unauth,編寫controller來處理該請求。
⑤ 自定義退出
修改配置類如下:
http.logout().logoutUrl("/logout") //退出登錄請求 .logoutSuccessUrl("/index") //注銷成功后跳轉(zhuǎn)地址 .permitAll();
還可以指定在退出時刪除某些cookie、注銷會話:
.deleteCookies("remember-me","sign") .invalidateHttpSession(true)
2、SpringSecurity的注解
通過方法上的注解我們可以實現(xiàn)在后端服務(wù)上細粒度的權(quán)限校驗。
主啟動類上要添加@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注解適合進入方法前的權(quá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)限表達式中可以使用hasRole、hasAnyRole、hasAuthority 以及hasAnyAuthority來靈活控制。
③ @PostAuthorize
先開啟注解功能: @EnableGlobalMethodSecurity(prePostEnabled = true) 。@PostAuthorize 注解很少使用,在方法執(zhí)行后再進行權(quán)限驗證,適合驗證帶有返回值的權(quán)限。
@RequestMapping("/testPostAuthorize") @ResponseBody @PostAuthorize("hasAnyAuthority('menu:system')") public String preAuthorize(){ System.out.println("test--PostAuthorize"); return "PostAuthorize"; }
④ @PostFilter
@PostFilter :權(quán)限驗證之后對數(shù)據(jù)進行過濾。表達式中的 filterObject 引用的是方法返回值List中的某一個元素。通常也很少使用。
如下留下用戶名是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: 進入控制器之前對數(shù)據(jù)進行過濾。
@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兩個注解在進入方法前進行角色、權(quán)限的控制。
進入方法前數(shù)據(jù)的過濾@PreFilter注解偶爾會看到,至于方法執(zhí)行完后進行校驗的兩個注解@PostAuthorize與@PostFilter幾乎不用。
到此這篇關(guān)于SpringSecurity請求授權(quán)規(guī)則配置與注解詳解的文章就介紹到這了,更多相關(guān)SpringSecurity配置與注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
命令行中 javac、java、javap 的使用小結(jié)
使用 java 命令運行一個.class文件,需要使用該類的全限定類名,同時需要在當前路徑下有該類的包層次文件夾,這篇文章主要介紹了命令行中 javac、java、javap 的使用小結(jié),需要的朋友可以參考下2023-07-07Java Springboot之Spring家族的技術(shù)體系
今天帶大家來學習Spring家族的技術(shù)體系,文中有非常詳細的圖文介紹及代碼示例,對正在學習java的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程
這篇文章主要介紹了Spring使用AspectJ的注解式實現(xiàn)AOP面向切面編程的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06