转载

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服务可能会是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文件来保护网页。

源码: GitHub 

原文  https://www.jdon.com/50603
正文到此结束
Loading...