- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- Spring Boot構建系統安全層的步驟
Spring Security 中采用的是管道-過(guò)濾器(Pipe-Filter)架構模式,這些過(guò)濾器鏈,構成了 Spring Security 的核心。如下圖所示:
項目一旦啟動(dòng),過(guò)濾器鏈將會(huì )實(shí)現自動(dòng)配置,如下圖所示:
UsernamePasswordAuthenticationFilter 用來(lái)檢查輸入的用戶(hù)名和密碼,代碼如下:
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } … }
BasicAuthenticationFilter 用來(lái)認證用戶(hù)的身份。
FilterSecurityInterceptor 用來(lái)判定該請求是否能夠訪(fǎng)問(wèn)目標 HTTP 端點(diǎn)。
SecurityContextHolder 存儲了應用的安全上下文對象 SecurityContext,包含系統請求中最近使用的認證信息。
一個(gè) HTTP 請求到達系統后,將通過(guò)一系列的 Filter 完成用戶(hù)認證,然后具體的工作交由 AuthenticationManager 完成,AuthenticationManager 成功驗證后會(huì )返回填充好的 Authentication 實(shí)例。
AuthenticationManager 是一個(gè)接口,其實(shí)現類(lèi) ProviderManager 會(huì )進(jìn)一步依賴(lài) AuthenticationProvider 接口完成具體的認證工作。
在 Spring Security 中存在一大批 AuthenticationProvider 接口的實(shí)現類(lèi),分別完成各種認證操作。在執行具體的認證工作時(shí),Spring Security 勢必會(huì )使用用戶(hù)詳細信息,UserDetailsService 服務(wù)就是用來(lái)對用戶(hù)詳細信息實(shí)現管理。
在 Spring Boot 中整合 Spring Security 框架首先需要引入依賴(lài):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
只要我們在代碼工程中添加了上述依賴(lài),包含在該工程中的所有 HTTP 端點(diǎn)都將被保護起來(lái)。
在引入 spring-boot-starter-security 依賴(lài)之后,Spring Security 會(huì )默認創(chuàng )建一個(gè)用戶(hù)名為“user”的賬號。當我們訪(fǎng)問(wèn) AccountController 的 “accounts/{accountId}” 端點(diǎn)時(shí),彈出如下界面:
同時(shí),控制臺日志打印如下:
Using generated security password: 17bbf7c4-456a-48f5-a12e-a680066c8f80
因此,訪(fǎng)問(wèn)該接口需要設置如下信息:
每次啟動(dòng)應用時(shí),通過(guò) Spring Security 自動(dòng)生成的密碼都會(huì )有所變化。如果我們想設置登錄賬號和密碼,可以在 application.yml 中配置如下:
spring: security: user: name: springcss password: springcss_password
初始化用戶(hù)信息所依賴(lài)的配置類(lèi)是 WebSecurityConfigurer 接口,在日常開(kāi)發(fā)中,我們往往是使用 WebSecurityConfigurerAdapter 類(lèi)并覆寫(xiě)其中的 configure(AuthenticationManagerBuilder auth) 的方法完成配置工作。
使用 AuthenticationManagerBuilder 類(lèi)創(chuàng )建一個(gè) AuthenticationManager 就能夠輕松實(shí)現基于內存、LADP 和 JDBC 的驗證。初始化所使用的用戶(hù)信息只需要指定用戶(hù)名(Username)、密碼(Password)和角色(Role)這三項數據即可。
使用基于內存的用戶(hù)信息存儲方案
@Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { builder.inMemoryAuthentication() .withUser("springcss_user") .password("password1") // 或者使用.authorities("ROLE_USER") .roles("USER") .and() .withUser("springcss_admin") .password("password2") .roles("USER", "ADMIN"); }
使用基于數據庫的用戶(hù)信息存儲方案
表結構如下:
create table users( username varchar_ignorecase(50) not null primary key, password varchar_ignorecase(500) not null, enabled boolean not null ); create table authorities ( username varchar_ignorecase(50) not null, authority varchar_ignorecase(50) not null, constraint fk_authorities_users foreign key(username) references users(username) ); create unique index ix_auth_username on authorities (username,authority);
Spring Security 的配置代碼如下:
@Autowired DataSource dataSource; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource) .usersByUsernameQuery("select username, password, enabled from Users where username=?") .authoritiesByUsernameQuery("select username, authority from UserAuthorities where username=?") .passwordEncoder(new BCryptPasswordEncoder()); }
擴展 UserDetails
public class SpringCssUser implements UserDetails { private static final long serialVersionUID = 1L; private Long id; private final String username; private final String password; private final String phoneNumber; // 省略getter/setter // 省略重寫(xiě)方法 }
擴展 UserDetailsService
@Service public class SpringCssUserDetailsService implements UserDetailsService { @Autowired private SpringCssUserRepository repository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { SpringCssUser user = repository.findByUsername(username); if (user != null) { return user; } throw new UsernameNotFoundException("SpringCSS User '" + username + "' not found"); } }
整合定制化配置
@Configuration public class SpringCssSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired SpringCssUserDetailsService springCssUserDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(springCssUserDetailsService); } }
在日常開(kāi)發(fā)過(guò)程中,我們需要對 Web 應用中的不同 HTTP 端點(diǎn)進(jìn)行不同粒度的權限控制。
使用配置方法
配置方法也是位于 WebSecurityConfigurerAdapter 類(lèi)中,但使用的是 configure(HttpSecurity http) 方法,如下代碼所示:
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 所有請求都需要認證 .anyRequest() // 允許認證用戶(hù)訪(fǎng)問(wèn) .authenticated() .and() // 需要使用表單進(jìn)行登錄 .formLogin() .and() // 使用 HTTP Basic Authentication 方法完成認證 .httpBasic(); }
Spring Security 還提供了一個(gè) access() 方法,允許開(kāi)發(fā)人員傳入一個(gè)表達式進(jìn)行更細粒度的權限控制,這里,我們將引入Spring 框架提供的一種動(dòng)態(tài)表達式語(yǔ)言—— SpEL(Spring Expression Language 的簡(jiǎn)稱(chēng))。
只要 SpEL 表達式的返回值為 true,access() 方法就允許用戶(hù)訪(fǎng)問(wèn),如下代碼所示:
@Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/orders") .access("hasRole('ROLE_USER')"); }
使用注解
Spring Security 提供了 @PreAuthorize 注解也可以實(shí)現類(lèi)似的效果,使用該注解代碼如下所示:
@RestController @RequestMapping(value="orders") public class OrderController { @PostMapping(value = "/") @PreAuthorize("hasRole(ROLE_ADMIN)") public void addOrder(@RequestBody Order order) { … } }
@PostAuthorize 主要用于請求結束之后檢查權限。
使用用戶(hù)級別保護服務(wù)訪(fǎng)問(wèn)
該級別是最基本的資源保護級別,只要是認證用戶(hù)就可能訪(fǎng)問(wèn)服務(wù)內的各種資源。
@Configuration public class SpringCssSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest() .authenticated(); } }
使用用戶(hù)+角色級別保護服務(wù)訪(fǎng)問(wèn)
該級別在認證用戶(hù)級別的基礎上,還要求用戶(hù)屬于某一個(gè)或多個(gè)特定角色。
@Configuration public class SpringCssSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/customers/**") .hasRole("ADMIN") .anyRequest() .authenticated(); } }
上述代碼表示只有"ADMIN"角色的認證用戶(hù)才能訪(fǎng)問(wèn)以"/customers/"為根地址的所有 URL。
使用用戶(hù)+角色+操作級別保護服務(wù)訪(fǎng)問(wèn)
該級別在認證用戶(hù)+角色級別的基礎上,對某些 HTTP 操作方法做了訪(fǎng)問(wèn)限制。
@Configuration public class SpringCssSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception{ http.authorizeRequests() .antMatchers(HttpMethod.DELETE, "/customers/**") .hasRole("ADMIN") .anyRequest() .authenticated(); } }
上述代碼的效果在于對“/customers”端點(diǎn)執行刪除操作時(shí),我們需要使用具有“ADMIN”角色的“springcss_admin”用戶(hù),否則會(huì )出現“access_denied”錯誤信息。
以上就是Spring Boot構建系統安全層的步驟的詳細內容,更多關(guān)于Spring Boot構建系統安全層的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站