Spring Boot安全保護使用教程

banq發表於2018-11-01

在這篇文章中,我將解釋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
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    public static void main (String [] args) {
            SpringApplication.run (WebSecurityConfiguration.class, args);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
       super.authenticationManagerBean return();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
         UserDetails user = User.builder()(). Username("user").Password(passwordEncoder().Encode( "secret")).roles ( "USER") build().;
         UserDetails UserAdmin = User.builder(). Username("admin").Password(passwordEncoder().Encode( "secret")).roles ( "ADMIN") build().;
        return new InMemoryUserDetailsManager (user, UserAdmin);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void set (http HttpSecurity) throws Exception {
        http
        .csrf().disable()
            .authorizeRequests()
            .antMatchers( "/" "/ index", "/ webpublico"). permitAll()
            .antMatchers( "/ webprivado"). authenticated()
            .antMatchers( "/ webadmin"). hasRole ( "ADMIN"). and()
                .formLogin()
                .loginPage( "/ login")
                .permitAll()
                .and()
                .logout() // get method for I desabilitado CSRF
                .permitAll();
    }
}





標註@SpringBootApplication 和 @EnableWebSecurity。第一個希望使用Spring Boot必注;第二個是指定啟用Web安全性; 老實說,這個標籤不是必需的,Spring Boot非常聰明,因為我們已經看到了專案中引入了安全性包(在pom.xml中)。但它提供了進一步的清晰度,但是,儘管是多餘的。


@SpringBootApplication
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {



現在,我們指定我們的類將繼承自WebSecurityConfigurerAdapter,因為我們會覆蓋該類的一些功能。因此,你需要了解Spring並檢視是否存在類實現介面WebSecurityConfigurer,後者又實現介面WebSecurityConfigurerAdapter,如果有,則使用該介面的功能來配置安全應用程式。

如果我們有一個實現此介面的類,Spring就不會訪問我們應用程式的任何頁面,但不是很實用。


@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
 super.authenticationManagerBean return();
}



現在,我們需要編寫一個函式 authenticationManagerBean 來返回負責管理身份驗證的類(顧名思義)。重要的是要知道在哪裡獲取(注入)物件型別AuthenticationManager, 因為只有透過它你才能控制Spring的安全性。


@Bean
@Override
public UserDetailsService userDetailsService() {
 UserDetails user = User.builder()(). Username("user").Password(passwordEncoder().Encode( "secret")).roles ( "USER") build().;
 UserDetails UserAdmin = User.builder(). Username("admin").Password(passwordEncoder().Encode( "secret")).roles ( "ADMIN") build().;
 return new InMemoryUserDetailsManager (user, UserAdmin);
}


在userDetailsService,我們定義可以訪問我們網站的使用者。在這種情況下,我們建立了兩個使用者:user和admin,每個使用者都有自己的密碼和角色。角色名稱USER和ADMIN可以自己定義,可以是你想要的任何字母。例如,USER_WITH_EYES - 事實是我們一旦使用該角色名,它必須與你定義的角色集合的角色名稱逐個字母匹配。

另請注意,在這種情況下,密碼是使用演算法Bcrypt加密的。我們透過呼叫函式來完成此操作,該函式 passwordEncoder使用Spring @Bean 標籤進行註釋。

也就是說,Spring需要知道我們用來儲存密碼的加密系統,並且它尋找實現介面的物件 PasswordEncoder:

@Bean
public PasswordEncoder passwordEncoder() {
 return new BCryptPasswordEncoder();
}



我想澄清一下,我們使用最簡單的方法來宣告使用者並將其儲存在記憶體中 InMemoryUserDetailsManager。在真實的程式中,它會使用JdbcUserDetailsManager,儲存在資料庫中。或者可能是包括實現介面UserDetailsManager的任何其他類, 如果我們使用LDAP服務可能會是LdapUserDetailsManager。


@Override
protected void set (http HttpSecurity) throws Exception {
   http.csrf().disable()
            .authorizeRequests()
            .antMatchers( "/" "/ index", "/ webpublico"). permitAll()
            .antMatchers( "/ webprivado"). authenticated()
            .antMatchers( "/ webadmin"). hasRole ( "ADMIN"). and()
                .formLogin()
                .loginPage( "/ login")
                .permitAll()
                .and()
                .logout() // get method for I desabilitado CSRF
                .permitAll();
}



由於我們需要定義應用程式的哪些部分將受到保護,因此角色必須具有訪問其每個部分的許可權。是的,是角色而非使用者,因為正如我們之前所說,當您定義使用者時,您必須分配一個角色。通常,過濾規則是適用於使用者所屬的組,要為每個資源設定許可權,我們要在函式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
public class WebController
{
@RequestMapping ({ "/", "index"})
public String start () {
return "index";
}
@RequestMapping ( "/webprivado")
public private String () {
"Private" return;
}
@RequestMapping ( "/webpublico")
public String loginpub () {
"Public" return;
}
@RequestMapping ( "/webadmin")
public String admin () {
return "admin";
}
@RequestMapping ( "/login")
public String login () {
return "login";
}
}




如上所述,@Controller定義Web請求的入口點。

@RequestMapping來指定URL並由每個函式處理。因此,當對URL,“ / ”或“ /index ” 的請求時,將呼叫函式start。

返回的字串將是Thymeleaf返回的模板,start函式將返回“index.html”模板,如下所示:


<! DOCTYPE html>
<Html xmlns = "http://www.w3.org/1999/xhtml" xmlns: th = "http://www.thymeleaf.org"
xmlns: sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<Head>
<Title> Home Page </ title>
</ Head>
<Body>
<H1> Home Page </ h1>
<P> <a th:href="@{/webpublico}"> Click here to view a page </a> public. </ P>
<P> If you are a regular user clicks </a> <a th:href="@{/webprivado}"> here to view a private page </ p>
<P> If you are a regular administrator </a> click <a th:href="@{/webadmin}"> here to see the profile Administrator </ p>
<Div sec: Authorize = "isAuthenticated ()">
Hello <span sec: authentication = "name"> someone </ span>
<P> <a th:href="@{/logout}"> Disconnect </a> </ p>
</ Div>
</ Body>
</ Html>




它看起來像純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檔案來保護網頁。

原始碼: GitHub 

相關文章