Spring Boot Security 入门—内存用户验证
简介
作为 spring 全家桶组件之一,spring security 是一个提供安全机制的组件,它主要解决两个问题:
- 认证:验证用户名和密码;
- 授权:对于不同的 url 权限不一样,只有当认证的用户拥有某个 url 的需要的权限时才能访问。
spring security 底层使用的是过滤器,针对 url 进行的拦截,对应到 java 中也就是类; 因此被称为粗粒度授权验证,就是验证 url ,当前用户是否有这个 url 的权限。
入门
创建项目
使用 idea 创建 spring boot 项目,勾选需要的组件:
- spring web
- spring security
或者创建项目后添加依赖:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-security</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency>
这里使用的是 jsp 作为模板,有关如何在 spring boot 中使用 jsp 作为模板请访问:
websecurityconfig
package top.cloudli.demo.security; import org.springframework.context.annotation.configuration; import org.springframework.security.config.annotation.authentication.builders.authenticationmanagerbuilder; import org.springframework.security.config.annotation.method.configuration.enableglobalmethodsecurity; import org.springframework.security.config.annotation.web.builders.httpsecurity; import org.springframework.security.config.annotation.web.configuration.enablewebsecurity; import org.springframework.security.config.annotation.web.configuration.websecurityconfigureradapter; import org.springframework.security.crypto.bcrypt.bcryptpasswordencoder; import org.springframework.security.crypto.password.passwordencoder; @configuration @enablewebsecurity @enableglobalmethodsecurity(prepostenabled=true) public class securityconfig extends websecurityconfigureradapter { @override protected void configure(authenticationmanagerbuilder auth) throws exception { passwordencoder encoder = new bcryptpasswordencoder(); auth.inmemoryauthentication() .passwordencoder(encoder) .withuser("root") .password(encoder.encode("root@123456")) .roles("root", "user") .and() .withuser("user") .password(encoder.encode("user@123456")) .roles("user"); } @override protected void configure(httpsecurity http) throws exception { http.authorizerequests() .antmatchers("/css/**") .permitall() // css 不用验证 .anyrequest() .authenticated() // 其它页面全部需要验证 .and() .formlogin() // 使用默认登录页面 .and() .exceptionhandling() .accessdeniedpage("/401") // 无权限时跳转的页面 .and() .logout(); } }
-
@enablewebsecurity
注解启用验证; -
@enableglobalmethodsecurity(prepostenabled=true)
注解允许我们在控制器的方法中使用@preauthorize
实现权限分割。
此处创建了两个用户并保存在内存中,分别是拥有 root 和 user 权限的 root 用户和仅拥有 user 权限的 user 用户。
fromlogin()
方法可以接着调用 loginpage()
指定一个自定义登录页面,这里使用的是默认登录页面。
编写页面
1.index.jsp,所有通过验证的用户都可以访问:
<%-- 任何通过验证的用户都能访问的页面 --%> <%@ page contenttype="text/html;charset=utf-8" language="java" %> <html> <head> <title>spring security demo application</title> <link rel="stylesheet" type="text/css" href="css/style.css"> </head> <body> <div class="content"> <h1>spring security in memory authentication</h1> <h2>这是被保护的页面(role_user)。</h2> </div> </body> </html>
2.root.jsp,只有拥有 root 权限的用户能访问:
<%-- 需要 role_root 才能访问的页面 --%> <%@ page contenttype="text/html;charset=utf-8" language="java" %> <html> <head> <title>root page</title> <link rel="stylesheet" type="text/css" href="css/style.css"> </head> <body> <div class="content"> <h1>root page</h1> <h2>你正在访问受保护的页面(role_root)。</h2> </div> </body> </html>
3.401.jsp,没有权限时跳转的页面:
<%-- 权限不够时跳转的页面 --%> <%@ page contenttype="text/html;charset=utf-8" language="java" %> <html> <head> <title>401 unauthorized</title> <link rel="stylesheet" type="text/css" href="css/style.css"> </head> <body class="error"> <div class="content"> <h1>401 unauthorized!</h1> <h2>你没有权限访问此页面。</h2> </div> </body> </html>
控制器
package top.cloudli.demo.controller; import org.springframework.security.access.prepost.preauthorize; import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.getmapping; @controller public class democontroller { @preauthorize("hasanyauthority('role_user')") @getmapping("/") public string index() { return "index"; } @preauthorize("hasanyauthority('role_root')") @getmapping("/root") public string root() { return "root"; } @getmapping("/401") public string accessdenied() { return "401"; } }
@preauthorize
注解指定了访问页面所需要的权限,这里的权限要加上 role_
前缀。
run
访问 http://localhost:8080/
将进入登录页面(这里使用的是 spring security 的默认登录页面):
使用刚才创建的内存用户 user 登录后将返回 index 页面:
访问 http://localhost:8080/root
,由于 user 用户没有 role_root 权限,跳转到 401 页面:
访问 http://localhost:8080/logout
将进入默认登出页面:
这里的登录和登出页面均可以使用自定义页面,只需要在自定义的页面中把数据通过 psot 请求提交到 /login
或 /logout
即可完成登录和登出。