在整合spring security之前,我将spring boot升级到了2.0.6,同时将分页插件pagehelper由1.1.0升级到1.2.5。
实际上,我整合spring security的目的主要有两个:即用户认证和权限校验,从功能讲我想像的需求应该是这样的:
根据上图的流程,过程如下:
1、pom.xml增加配置
老套路,增加spring security资源坐标:
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、先创建demo控制器
demo控制器返回各页面及相关结果:
package com.whowii.website4.manage.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/manage/demo")
public class DemoController {
@GetMapping("/index")
public String index() {
// 默认首页,谁都可以访问
return "/manage/demo/demo-index";
}
@GetMapping("/login")
public String login() {
// 登录页面,谁都可以访问
return "/manage/demo/demo-login";
}
@GetMapping("/error")
@ResponseBody
public String error() {
// 登录失败页面,所有用户登录失败时提示错误信息
return "登录失败,账号密码错误";
}
@GetMapping("/hello")
@ResponseBody
public String hello() {
// hello 请求,任务用户都可以访问
return "hello";
}
@GetMapping("/info1")
@ResponseBody
public String info1() {
// 信息页面,只有 ADMIN 角色才能访问
return "admin info1";
}
@GetMapping("/info2")
@ResponseBody
public String info2() {
// 信息页面,只有 USER 角色才能访问
return "user info2";
}
}
/manage/demo/index:首页,对应的视图为demo-index.html
/manage/demo/login:登录页面,对应的视图为 demo-login.html
/manage/demo/error:登录失败提示页面,对应的视图为
/manage/demo/hello:hello world页面,所有用户都可以访问
/manage/demo/info1:admin 角色才可以访问的信息页面
/manage/demo/info2:user角色才可以访问的信息页面
3、创建视图页
3.1 demo-index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>demo - index</title>
</head>
<body>
<div class="starter-template">
<h1>Spring Boot +Spring Security 示例</h1>
<h2>1. 打开 <a href="/manage/demo/hello">游客页面(/manage/demo/hello)</a></h2>
<h2>2. 打开 <a href="/manage/demo/info1">管理员页面(/manage/demo/info1)</a></h2>
<h2>3. 打开 <a href="/manage/demo/info2">用户页面(/manage/demo/info2)</a></h2>
<br/><br/>
<h2>4. 打开 <a href="/manage/demo/login">登录页面(/manage/demo/login)</a></h2>
<h2>5. 打开 <a href="/manage/demo/exit">退出登录(/manage/demo/exit)</a></h2>
</div>
</body>
</html>
首页只是做了各页面的链接,方便跳转。
3.2 demo-login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
</head>
<body>
<form method="post" action="/manage/demo/login">
<fieldset>
<h1>登录</h1>
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg" placeholder="用户名" required="true" autofocus="true" />
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg" placeholder="密码" required="true" />
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="登录" />
</div>
</div>
</fieldset>
</form>
</body>
</html>
登录页面(表单),需要注意两点:一是用户名和密码字段名,二是表单提交到的action,这与配置对应,后方会说到。
4、继承 WebSecurityConfigurerAdapter
package com.whowii.website4.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("SecurityConfig.configure > http");
http.csrf().disable()
.authorizeRequests()
.antMatchers("/manage/demo/hello").permitAll() // 此页面允许任何人访问,即使未登录
.antMatchers("/manage/demo/info1").hasAnyRole("ADMIN") // 仅允许 ADMIN 角色的用户访问
.antMatchers("/manage/demo/info2").hasAnyRole("USER") // 仅允许 USER 角色的用户访问
.anyRequest().denyAll() // 其他资源禁止访问
.and()
.formLogin()
.loginPage("/manage/demo/login") // 自定义登录页面
.failureUrl("/manage/demo/error") // 登录错误页面
.permitAll() // 允许任何用户访问
.and()
.logout()
.logoutUrl("/manage/demo/exit") // 退出登录
.logoutSuccessUrl("/manage/demo/index") // 退出登录成功返回的页面
.permitAll() // 也允许任务用户访问
.and()
.exceptionHandling();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("SecurityConfig.configure > withUser");
auth.inMemoryAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("123")).roles("ADMIN")
.and()
.withUser("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER");
}
}
仔细看下相关的配置,定义了登录页面、登录失败页面、退出页面、退出成功页面等相关配置,这与控制器相对应。
其中,配置了2个固定的用户,分别是 admin(密码是123),角色是ADMIN,第二个用户是user(密码是123),角色是USER。
5、测试结果
5.1 访问首页
启用应用,访问:http://127.0.0.1:8080/manage/demo/index 如下:
5.2 访问无需授权页面
点击其中的链接1,或者在浏览器中直接访问/manage/demo/hello如下:
5.3 访问需要授权页面
访问/manage/demo/info1或/manage/demo/info2都会跳转到登录页面,原因很简单,因为配置中定义了这两个资源需要具有相应的权限才可以访问,所以必须先登录:
5.4 访问已授权页面
使用admin/123登录后,访问链接2(/manage/demo/info1)或者直接在浏览器地址栏中访问,提示信息如下:
5.5 访问未授权页面
在未登录时访问/manage/demi/info2会跳转到登录页面,但若在admin用户登录时访问,则会提示如下信息:
为什么?很简单,因为admin账号是ADMIN角色,而/manage/demo/info2需要USER角色才能访问。假如你使用user/123登录,就可以访问,但使用user登录后则访问不了/manage/demo/info1,道理一样。
5.6 切换用户
当使用admin登录后,若需要使用user登录,则需要先访问/manage/demo/exit退出登录状态后,重新访问/manage/demo/login页面,使用user/123登录。
5.7 登录失败
假如你在登录时使用了错误的账号或密码,则会提示如下信息:
到此,演示了登录、权限认证的相关示例。下一遍,将说明如何使用数据中的用户信息进行判断。