Spring Boot 2.1 中如何使用Spring Security 5进行安全控制.md

原创
2019/04/06 09:36
阅读数 370

我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面。要实现访问控制的方法多种多样,可以通过Aop、拦截器实现,也可以通过框架实现(如:Apache Shiro、Spring Security)。

本文将具体介绍在Spring Boot中如何使用Spring Security进行安全控制。

准备工作

首先,构建一个简单的Web工程,以用于后续添加安全控制。

添加依赖

<dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

Web层实现请求映射

@Controller
public class HomeController {

    @GetMapping({"/", "/home"})
    public String homeUI() {
        return "home";
    }

    @GetMapping("test")
    @ResponseBody
    public String test() {
        return "test";
    }
}
  • / 或则/home:映射到 home.html
  • /test:以json 形式返回字符串"test"

实现映射的页面

  • src/main/resources/templates/home.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-springsecurity3">
<head>
    <title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
    <input type="submit" value="注销"/>
</form>
</body>
</html>

可以看到在home.html中提供到/home的链接,显然在这里没有任何安全控制,所以点击链接后就可以直接跳转到home.html页面。

整合Spring Security

在这一节,我们将对/hello页面进行权限控制,必须是授权用户才能访问。当没有权限的用户访问后,跳转到登录页面。

添加依赖

在pom.xml中添加如下配置,引入对Spring Security的依赖。

<dependencies>
    ...
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    ...
</dependencies>

Spring Security配置

创建Spring Security的配置类WebSecurityConfig,具体如下:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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


    /**
     * configure(AuthenticationManagerBuilder auth)方法,
     * 在内存中创建了一个用户,该用户的名称为user,密码为password,用户角色为USER
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password(passwordEncoder().encode("admin"))
                //.password("admin")
                .roles("ADMIN");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    /**
     * <pre>
     * 继承WebSecurityConfigurerAdapter,并重写它的方法来设置一些web安全的细节
     * configure(HttpSecurity http)方法
     * 通过authorizeRequests()定义哪些URL需要被保护、哪些不需要被保护。
     * 例如以上代码指定了/login和/test不需要任何认证就可以访问,其他的路径都必须通过身份验证。
     * 通过formLogin()定义当需要用户登录时候,转到的登录页面。
     * </pre>
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
			.authorizeRequests()
                .antMatchers("/login","/test").permitAll()
				.anyRequest().authenticated()
				.and()
			.formLogin()
                .loginPage("/login").permitAll();
        // @formatter:on
    }
}

  • 通过@EnableWebSecurity注解开启Spring Security的功能

    这个注解可以不加,因为org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 集成后已经使用了该注解。

  • 继承WebSecurityConfigurerAdapter,并重写它的方法来设置一些web安全的细节

  • configure(HttpSecurity http)
    

    方法

    • 通过authorizeRequests()定义哪些URL需要被保护、哪些不需要被保护。例如以上代码指定了/login和/test不需要任何认证就可以访问,其他的路径都必须通过身份验证。
    • 通过formLogin()定义当需要用户登录时候,转到的登录页面。

新增登录请求与页面

在完成了Spring Security配置之后,我们还缺少登录的相关内容。

HelloController中新增/login请求映射至login.html

@Controller
public class LoginController {
    @GetMapping("login")
    public String login() {
        return "login";
    }
}

新增登录页面:src/main/resources/templates/login.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-springsecurity3">
<head>
    <title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
    用户名或密码错
</div>
<div th:if="${param.logout}">
    您已注销成功
</div>
<form th:action="@{/login}" method="post">
    <div><label> 用户名 : <input type="text" name="username"/> </label></div>
    <div><label> 密 码 : <input type="password" name="password"/> </label></div>
    <div><input type="submit" value="登录"/></div>
</form>
</body>
</html>

可以看到,实现了一个简单的通过用户名和密码提交到/login的登录方式。

根据配置,Spring Security提供了一个过滤器来拦截请求并验证用户身份。如果用户身份认证失败,页面就重定向到/login?error,并且页面中会展现相应的错误信息。若用户想要注销登录,可以通过访问/login?logout请求,在完成注销之后,页面展现相应的成功消息。

到这里,我们启用应用,并访问http://localhost:8080/,可以正常访问。但是访问http://localhost:8080/home的时候被重定向到了http://localhost:8080/login页面,因为没有登录,用户没有访问权限,通过输入用户名user和密码password进行登录后,跳转到了Hello World页面,再也通过访问http://localhost:8080/login?logout,就可以完成注销操作。

代码示例

http://blog.didispace.com/springbootsecurity/

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部