新聞中心
這篇文章將為大家詳細講解有關(guān)SpringBoot 中Security如何使用,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
專注于為中小企業(yè)提供網(wǎng)站設(shè)計制作、做網(wǎng)站服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)泰順免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上千企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
什么是SpringSecurity
Security是Spring全家桶中一個安全框架,他的擴展能力非常的強,底層是一條過濾器鏈。通過簡單的配置就可以使用,但通過自己的DIY,可以把每個權(quán)限細化到每個鏈接上去。
shiro沒有學(xué),但只推薦學(xué)一個安全框架
這里搭建的學(xué)習(xí)項目都是使用SpringBoot
獲取SpringSecurity
你可以在maven官網(wǎng)獲取最新版本
org.springframework.boot spring-boot-starter-security 2.4.2
開始一個SpringBoot項目
4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.2 com.pipihao securitylearn 0.0.1-SNAPSHOT securitylearn Demo project for Spring Boot 1.8 com.alibaba druid 1.1.21 org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.4 MySQL mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.security spring-security-test test org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok
項目配置文件
server: port: 8001 spring: datasource: url: jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver thymeleaf: cache: false # 因為Thymeleaf很多有默認配置,所以只關(guān)了這個緩存,方便刷新
數(shù)據(jù)庫文件
數(shù)據(jù)庫版本為 8.0
運行項目
登錄
用戶名:user
密碼:控制臺輸出的這密碼
配置Security
方法一:通過配置文件修改登錄賬號密碼
spring: security: user: name: xx password: xx
方法二:通過自定義配置SecurityConfig配置類
WebSecurityConfigurerAdapter 類是是Security內(nèi)置提供了一個默認身份驗證的抽象類,繼承此抽象類實現(xiàn)configure方法則可以對驗證操作實現(xiàn)DIY。[于官方文檔 6.3 標題可見]
UserDetailsService接口:查詢數(shù)據(jù)庫用戶名和密碼過程
創(chuàng)建類繼承UsernamePasswordAuthenticationFilter,重寫三個方法
*創(chuàng)建類實現(xiàn)UserDetailService,編寫查詢數(shù)據(jù)過程,返回User對象,這個User對象是安全框架提供對象。
PasswordEncoder: 數(shù)據(jù)加密接口,用于返回User對象里面的密碼加密
方法三:自定義配置類UserDetailsService
定義不驗證鏈接
@Override protected void configure(HttpSecurity http) throws Exception { /* 使用and()方法表示關(guān)閉XML標記的Java配置,它允許我們繼續(xù)配置父標記。如果您閱讀代碼,它也是有道理的。我想配置授權(quán)請求并配置表單登錄并配置HTTP基本身份驗證。 */ http .authorizeRequests() .antMatchers("/","/no").permitAll() //可以直接訪問的路徑 .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") //配置登錄路徑 .loginProcessingUrl("/doLogin") .defaultSuccessUrl("/hallo") .permitAll() ; //設(shè)置 登錄的網(wǎng)頁 http.csrf().disable(); //如果注釋了這一行,全部要用_csrf的對象來驗證了 }
配置訪問權(quán)限/角色
如果是配置訪問角色則使用是hasRole與hasAnyRole
這里非常建議點一下看一下hasRole的源碼使用Role的時候,User的權(quán)限列表是需要加ROLE_前綴的
這里直接使用的是hasAnyAuthority,還有一個方法是hasAuthority
前者可以配置多個權(quán)限,而后者只能配置一個權(quán)限
接口只是顯示一個字符串
@GetMapping("test") public String sayTest(){ return "Test"; }
SecurityConfig代碼
@Override protected void configure(HttpSecurity http) throws Exception { /* 使用and()方法表示關(guān)閉XML標記的Java配置,它允許我們繼續(xù)配置父標記。如果您閱讀代碼,它也是有道理的。我想配置授權(quán)請求并配置表單登錄并配置HTTP基本身份驗證。 */ http .authorizeRequests() .antMatchers("/","/no").permitAll() //可以直接訪問的路徑 .antMatchers("/test").hasAnyAuthority("admin") // 訪問權(quán)限 .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") //配置登錄路徑 .loginProcessingUrl("/doLogin") .defaultSuccessUrl("/hallo") .permitAll() ; //設(shè)置 登錄的網(wǎng)頁 http.csrf().disable(); //如果注釋了這一行,全部要用_csrf的對象來驗證了 }
UserDetailsImpl代碼
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if(StringUtils.isEmpty(username)){ throw new RuntimeException("用戶名不能為空"); } IUser iUser= userMapper.getUserByUsername(username); if(iUser == null){ throw new UsernameNotFoundException("無此用戶"); } /*此處查詢用戶角色*/ ListgrantedAuthorityList = AuthorityUtils.createAuthorityList("admin"); // 權(quán)限的列表 return new User(iUser.getUsername(),bCryptPasswordEncoder.encode(iUser.getPassword()),grantedAuthorityList); }
自定義403界面
// 在此方法內(nèi)加上一行 protected void configure(HttpSecurity http) http.exceptionHandling().accessDeniedPage("/unauth.html");
權(quán)限注解
@Secured
判斷是否有角色,這里匹配的角色需要加前綴ROLE_
@GetMapping("update") @Secured({"ROLE_manager"}) public String update(){ return "update"; }
使用其功能時需要在application類上開起
@SpringBootApplication @MapperScan("com.pipihao.securitylearn.mapper") @EnableGlobalMethodSecurity(securedEnabled = true) public class SecuritylearnApplication { public static void main(String[] args) { SpringApplication.run(SecuritylearnApplication.class, args); } }
UserDetailsServiceImpl
ListgrantedAuthorityList = AuthorityUtils.createAuthorityList("admin","ROLE_manager");
@PreAuthorize & @PostAuthorize
此注解即有權(quán)限驗證功能,又有角色驗證功能
@GetMapping("pre1") @PreAuthorize("hasAnyRole('ROLE_manager')") public String prePost1(){ return "prePost1"; } @GetMapping("pre2") @PreAuthorize("hasAnyAuthority('admin')") public String prePost2(){ return "prePost2"; }
@SpringBootApplication @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecuritylearnApplication { public static void main(String[] args) { SpringApplication.run(SecuritylearnApplication.class, args); } }
@PostAuthorize 與@PreAuthorize的區(qū)別就是,Pre會先攔截后執(zhí)行,而PostAuthorize是先執(zhí)行,后攔截
所以我例子中沒有過多的講
@PreFilter & @PostFilter
Pre是過濾上傳的數(shù)據(jù),Post過濾返回的數(shù)據(jù)
@GetMapping("list") @PostFilter("filterObject.username != 'admin' ") public Listlist(){ List iUsers = new ArrayList<>(); iUsers.add(new IUser(1,"admin","123")); iUsers.add(new IUser(2,"user","123")); return iUsers; } // Applicationo類上還是要加上下面這個注解,并設(shè)置屬性值 @EnableGlobalMethodSecurity(prePostEnabled = true)
效果圖
上傳則是同理,通過注解寫好判斷,然后測試即可,注:PreFilter過濾的也只是集合和數(shù)組
用戶注銷
/*配置退出登錄*/ http.logout().logoutUrl("/logout").logoutSuccessUrl("no").permitAll();
登錄后,直接通過瀏覽器,訪問此路徑即可(是的,就是如此)
location.href='/logout';
自動登錄
下面是尚硅谷老師寫的原理圖和執(zhí)行流程
如果是微服務(wù),則把數(shù)據(jù)庫改成redis,把cookie改成jwt生成的token
Security 中的一個類內(nèi)JdbcTokenRepositoryImpl
的常量CREATE_TABLE_SQL
create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
有興趣的可以看看源碼沒興趣的直接在你使用的數(shù)據(jù)庫內(nèi)執(zhí)行上面這行sql創(chuàng)建一個保存登錄信息的表
JdbcTokenRepositoryImpl 是PersistentTokenRepository實現(xiàn)類
下面這種寫那么應(yīng)該是多態(tài)了
@Autowired private DataSource dataSource; @Bean public PersistentTokenRepository persistentTokenRepository(){ JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); jdbcTokenRepository.setDataSource(dataSource); //jdbcTokenRepository.setCreateTableOnStartup(true); 設(shè)置啟動時創(chuàng)建自動登錄表 return jdbcTokenRepository; }
SecurityConfig的方法
@Override protected void configure(HttpSecurity http) throws Exception { /*自定義403鏈接*/ http.exceptionHandling().accessDeniedPage("/unauth.html"); /*配置退出登錄*/ http.logout().logoutUrl("/logout").logoutSuccessUrl("/no").permitAll(); /* 使用and()方法表示關(guān)閉XML標記的Java配置,它允許我們繼續(xù)配置父標記。如果您閱讀代碼,它也是有道理的。我想配置授權(quán)請求并配置表單登錄并配置HTTP基本身份驗證。 */ http .authorizeRequests() .antMatchers("/","/no").permitAll() //可以直接訪問的路徑 .antMatchers("/test").hasAnyAuthority("admin") .antMatchers("/unauth").hasAnyAuthority("xxx") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") //配置登錄路徑 .loginProcessingUrl("/doLogin") .defaultSuccessUrl("/hallo") .permitAll() // -------------------就是下面這坨 .and() .rememberMe().tokenRepository(persistentTokenRepository()) .tokenValiditySeconds(60) // 自動保存的時間,秒為單位 .userDetailsService(userDetailsService) ; //設(shè)置 登錄的網(wǎng)頁 http.csrf().disable(); //如果注釋了這一行,全部要用_csrf的對象來驗證了 }
下面是登錄界面
然后在登錄的時候打個勾,就可以自動登錄了
在DB中會出現(xiàn)如下的信息
CSRF指令認證
第一步把下面這一行注釋了就開啟了,也就是說他其實是默認開啟的
如果沒有關(guān)閉,則會NullPointerException
//http.csrf().disable();
Spring Security CSRF 會針對Patch,Post,Put,Delete方法進行防護。(都是一些要更改數(shù)據(jù)的方法)
系統(tǒng)默認提供了一個csrfToken對象放在HttpSession中,也就是我們所見到了_csrf對象
此對象可以直接使用
開啟CSRF后,則登錄的時【POST】,也需要驗證CSRF,而使用HttpSession則需要使用模板引擎,這里我們使用的是Thymeleaf而非JSP。(大同小異)
注:使用Thymeleaf的時候,類上的Controller注解不能寫成RestController,不然無法生效的
@Controller public class LoginController { @GetMapping("login") public String login(){ return "login"; } }
登錄
切記,默認開了CSRF,則每個表單中應(yīng)當手動添加一個隱藏域
當Thymeleaf因為你使用了th,則自動給你生成了。
所以 th:action="'/doLogin'"
這樣寫可以省事
如下圖
關(guān)于SpringBoot 中Security如何使用就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
分享名稱:SpringBoot中Security如何使用
標題來源:http://www.ef60e0e.cn/article/jpgddj.html