Spring Boot安全保護使用教程
在這篇文章中,我將解釋Spring如何管理安全性。當然,我不會涵蓋所有內容 - 安全問題將可以寫成一本大書,但我們至少會看看如何保護網站。如何使用兩個Java類及其HTML檔案來保護您的網頁。
Spring Boot實際上非常簡單,因為我們只要使用Spring的啟動器即可,啟動器包括Web,Thymeleaf,當然還有Security。
這些啟動器會打包在pom.xml檔案中。
Thymeleaf 是與Spring無縫整合並建立網頁模板的軟體,它與JSP類似,但Thymeleaf是一個更加改進的版本。或者,更像JSF,更JavaEE一些。案例中使用它的HTML頁面與Spring的類無縫整合。
如果我們要在網頁中看到登入的使用者名稱,就需要使用庫安全的Thymeleaf for Spring。為此,我們將在pom.xml檔案中包含以下行。
<dependency> <groupId> org.thymeleaf.extras <groupId/> <artifactId> thymeleaf-extras-springsecurity4 <artifactId/> <version> 3.0.3.RELEASE <version/> <dependency/>
現在,我們開始宣告我們的第一個類,我稱之為 WebSecurityConfiguration.java:
@SpringBootApplication @EnableWebSecurity <b>public</b> <b>class</b> WebSecurityConfiguration <b>extends</b> WebSecurityConfigurerAdapter { <b>public</b> <b>static</b> <b>void</b> main (String [] args) { SpringApplication.run (WebSecurityConfiguration.<b>class</b>, args); } @Bean @Override <b>public</b> AuthenticationManager authenticationManagerBean() throws Exception { <b>super</b>.authenticationManagerBean <b>return</b>(); } @Bean @Override <b>public</b> UserDetailsService userDetailsService() { UserDetails user = User.builder()(). Username(<font>"user"</font><font>).Password(passwordEncoder().Encode( </font><font>"secret"</font><font>)).roles ( </font><font>"USER"</font><font>) build().; UserDetails UserAdmin = User.builder(). Username(</font><font>"admin"</font><font>).Password(passwordEncoder().Encode( </font><font>"secret"</font><font>)).roles ( </font><font>"ADMIN"</font><font>) build().; <b>return</b> <b>new</b> InMemoryUserDetailsManager (user, UserAdmin); } @Bean <b>public</b> PasswordEncoder passwordEncoder() { <b>return</b> <b>new</b> BCryptPasswordEncoder(); } @Override <b>protected</b> <b>void</b> set (http HttpSecurity) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers( </font><font>"/"</font><font> </font><font>"/ index"</font><font>, </font><font>"/ webpublico"</font><font>). permitAll() .antMatchers( </font><font>"/ webprivado"</font><font>). authenticated() .antMatchers( </font><font>"/ webadmin"</font><font>). hasRole ( </font><font>"ADMIN"</font><font>). and() .formLogin() .loginPage( </font><font>"/ login"</font><font>) .permitAll() .and() .logout() </font><font><i>// get method for I desabilitado CSRF</i></font><font> .permitAll(); } } </font>
標註@SpringBootApplication 和 @EnableWebSecurity。第一個希望使用Spring Boot必注;第二個是指定啟用Web安全性; 老實說,這個標籤不是必需的,Spring Boot非常聰明,因為我們已經看到了專案中引入了安全性包(在pom.xml中)。但它提供了進一步的清晰度,但是,儘管是多餘的。
@SpringBootApplication @EnableWebSecurity <b>public</b> <b>class</b> WebSecurityConfiguration <b>extends</b> WebSecurityConfigurerAdapter {
現在,我們指定我們的類將繼承自WebSecurityConfigurerAdapter,因為我們會覆蓋該類的一些功能。因此,你需要了解Spring並檢視是否存在類實現介面WebSecurityConfigurer,後者又實現介面WebSecurityConfigurerAdapter,如果有,則使用該介面的功能來配置安全應用程式。
如果我們有一個實現此介面的類,Spring就不會訪問我們應用程式的任何頁面,但不是很實用。
@Bean @Override <b>public</b> AuthenticationManager authenticationManagerBean() throws Exception { <b>super</b>.authenticationManagerBean <b>return</b>(); }
現在,我們需要編寫一個函式 authenticationManagerBean 來返回負責管理身份驗證的類(顧名思義)。重要的是要知道在哪裡獲取(注入)物件型別AuthenticationManager, 因為只有通過它你才能控制Spring的安全性。
@Bean @Override <b>public</b> UserDetailsService userDetailsService() { UserDetails user = User.builder()(). Username(<font>"user"</font><font>).Password(passwordEncoder().Encode( </font><font>"secret"</font><font>)).roles ( </font><font>"USER"</font><font>) build().; UserDetails UserAdmin = User.builder(). Username(</font><font>"admin"</font><font>).Password(passwordEncoder().Encode( </font><font>"secret"</font><font>)).roles ( </font><font>"ADMIN"</font><font>) build().; <b>return</b> <b>new</b> InMemoryUserDetailsManager (user, UserAdmin); } </font>
在userDetailsService,我們定義可以訪問我們網站的使用者。在這種情況下,我們建立了兩個使用者:user和admin,每個使用者都有自己的密碼和角色。角色名稱USER和ADMIN可以自己定義,可以是你想要的任何字母。例如,USER_WITH_EYES - 事實是我們一旦使用該角色名,它必須與你定義的角色集合的角色名稱逐個字母匹配。
另請注意,在這種情況下,密碼是使用演算法Bcrypt加密的。我們通過呼叫函式來完成此操作,該函式 passwordEncoder使用Spring @Bean 標籤進行註釋。
也就是說,Spring需要知道我們用來儲存密碼的加密系統,並且它尋找實現介面的物件 PasswordEncoder:
@Bean <b>public</b> PasswordEncoder passwordEncoder() { <b>return</b> <b>new</b> BCryptPasswordEncoder(); }
我想澄清一下,我們使用最簡單的方法來宣告使用者並將其儲存在記憶體中 InMemoryUserDetailsManager。在真實的程式中,它會使用JdbcUserDetailsManager,儲存在資料庫中。或者可能是包括實現介面UserDetailsManager的任何其他類, 如果我們使用LDAP/">LDAP服務可能會是LdapUserDetailsManager。
@Override <b>protected</b> <b>void</b> set (http HttpSecurity) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers( <font>"/"</font><font> </font><font>"/ index"</font><font>, </font><font>"/ webpublico"</font><font>). permitAll() .antMatchers( </font><font>"/ webprivado"</font><font>). authenticated() .antMatchers( </font><font>"/ webadmin"</font><font>). hasRole ( </font><font>"ADMIN"</font><font>). and() .formLogin() .loginPage( </font><font>"/ login"</font><font>) .permitAll() .and() .logout() </font><font><i>// get method for I desabilitado CSRF</i></font><font> .permitAll(); } </font>
由於我們需要定義應用程式的哪些部分將受到保護,因此角色必須具有訪問其每個部分的許可權。是的,是角色而非使用者,因為正如我們之前所說,當您定義使用者時,您必須分配一個角色。通常,過濾規則是適用於使用者所屬的組,要為每個資源設定許可權,我們要在函式protected void configure(HttpSecurity http)中配置接受的物件HttpSecurity。
我將逐行解釋在這個函式中做了什麼:
csrf(). disable()
首先,我們正在研究CSRF禁用控制。CRSF代表 跨站點請求偽造, 禁用CRSF有副作用,可以使用HTTP GET請求執行會話登出,然後預設只能通過POST請求完成:
.authorizeRequests ().antMatchers("/","/ index", "/webpublico").permitAll ()
我們指定使用任何字串“/”,“/ index”,“/ webpublico”等路由的URL將不具有安全性。每個人都可以訪問。
antMatchers ("/webprivado").authenticated()
我們指定請求路徑“/webprivado”需要使用者進行身份驗證才能訪問,不需要指定屬於什麼角色。
.antMatchers("/webadmin").hasRole("ADMIN")
只有屬於ADMIN角色的使用者才能訪問URL “/ webadmin”。
該函式antMatchers是可使用正則表示式,因此,例如,如果我們想要將規則應用於依賴於路由的所有規則,我們可以將此:
http.antMatchers(“/ users / **”).hasRole(“USER”)
指定訪問URL是/users/XXX的任何請求只能是屬於USER角色的使用者發出的。
.formLogin().loginPage("/login").permitAll()
我們指定登入頁面為“ / login ”並允許其訪問所有人。
logout(). permitAll()
我們指定可讓所有人訪問退出頁面。預設情況下,此頁面由URL“ /logout ”響應。
我們已經定義了我們網站的安全性。現在,我們只要定義頁面的入口點。完成類 WebController.java。
@Controller <b>public</b> <b>class</b> WebController { @RequestMapping ({ <font>"/"</font><font>, </font><font>"index"</font><font>}) <b>public</b> String start () { <b>return</b> </font><font>"index"</font><font>; } @RequestMapping ( </font><font>"/webprivado"</font><font>) <b>public</b> <b>private</b> String () { </font><font>"Private"</font><font> <b>return</b>; } @RequestMapping ( </font><font>"/webpublico"</font><font>) <b>public</b> String loginpub () { </font><font>"Public"</font><font> <b>return</b>; } @RequestMapping ( </font><font>"/webadmin"</font><font>) <b>public</b> String admin () { <b>return</b> </font><font>"admin"</font><font>; } @RequestMapping ( </font><font>"/login"</font><font>) <b>public</b> String login () { <b>return</b> </font><font>"login"</font><font>; } } </font>
如上所述,@Controller定義Web請求的入口點。
@RequestMapping來指定URL並由每個函式處理。因此,當對URL,“ / ”或“ /index ” 的請求時,將呼叫函式start。
返回的字串將是Thymeleaf返回的模板,start函式將返回“index.html”模板,如下所示:
<! DOCTYPE html> <Html xmlns = <font>"http://www.w3.org/1999/xhtml"</font><font> xmlns: th = </font><font>"http://www.thymeleaf.org"</font><font> xmlns: sec = </font><font>"http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"</font><font>> <Head> <Title> Home Page </ title> </ Head> <Body> <H1> Home Page </ h1> <P> <a th:href=</font><font>"@{/webpublico}"</font><font>> Click here to view a page </a> <b>public</b>. </ P> <P> If you are a regular user clicks </a> <a th:href=</font><font>"@{/webprivado}"</font><font>> here to view a <b>private</b> page </ p> <P> If you are a regular administrator </a> click <a th:href=</font><font>"@{/webadmin}"</font><font>> here to see the profile Administrator </ p> <Div sec: Authorize = </font><font>"isAuthenticated ()"</font><font>> Hello <span sec: authentication = </font><font>"name"</font><font>> someone </ span> <P> <a th:href=</font><font>"@{/logout}"</font><font>> Disconnect </a> </ p> </ Div> </ Body> </ Html> </font>
它看起來像純HTML?這是使用Thymeleaf標準HTML標記的優勢之一。我不會在這裡解釋這個語言,但我將解釋一些使用的標籤:
<a th:href="@{/webpublico}">
建立指向“/webpublico” 的連結。這就像使用“tag <A href="/webpublico">。
<div sec: Authorize = "isAuthenticated ()">
如果使用者通過身份驗證,這是唯一將在DIV中呈現的程式碼。換句話說,如果使用者未登入,則它不會顯示在DIV標籤之間的網頁上。
<span sec: authentication = "name"> someone </ span>
如果使用者使用其使用者名稱登入,則會顯示標籤span之間的內容。在這種情況下,它顯示了某人使用者名稱。
有了這個,我們有一個安全的應用程式!是的,我們只使用兩個Java類及其相應的HTML檔案來保護網頁。
原始碼:OAuthServer" rel="nofollow,noindex" target="_blank">GitHub