1. 引言
代码已提交至Github,有兴趣的同学可以下载看看:https://github.com/ylw-github/SpringBoot-Security-Demo
上一篇博客《微服务技术系列教程(37)- SpringBoot -SpringSecurity简介》主要讲解了SpringSecurity介绍以及应用场景。
本文主要讲解SpringBoot整合SpringSecurity,学习之前,先来了解一个概念“Basic认证”。
什么是Basic认证?
- 在HTTP协议进行通信的过程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份证的方法,当一个客户端向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。
- 客户端在接收到HTTP服务器的身份认证要求后,会提示用户输入用户名及密码,然后将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中,如当用户名为ylw,密码为:123456时,客户端将用户名和密码用“:”合并,并将合并后的字符串用BASE64加密为密文,并于每次请求数据时,将密文附加于请求头(Request Header)中。
- HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。
1.添加Maven依赖:
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.M7
pom
import
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-freemarker
spring-boot 整合security -->
org.springframework.boot
spring-boot-starter-security
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
2.application.yml
# 配置freemarker
spring:
freemarker:
# 设置模板后缀名
suffix: .ftl
# 设置文档类型
content-type: text/html
# 设置页面编码格式
charset: UTF-8
# 设置页面缓存
cache: false
# 设置ftl文件路径
template-loader-path:
- classpath:/templates
# 设置静态文件路径,js,css等
mvc:
static-path-pattern: /static/**
3.前端资源 4.请求Controller
@Controller
public class OrderController {
// 首页
@RequestMapping("/")
public String index() {
return "index";
}
// 查询订单
@RequestMapping("/showOrder")
public String showOrder() {
return "showOrder";
}
// 添加订单
@RequestMapping("/addOrder")
public String addOrder() {
return "addOrder";
}
// 修改订单
@RequestMapping("/updateOrder")
public String updateOrder() {
return "updateOrder";
}
// 删除订单
@RequestMapping("/deleteOrder")
public String deleteOrder() {
return "deleteOrder";
}
// 自定义登陆页面
@GetMapping("/login")
public String login() {
return "login";
}
}
2.2 Security配置
配置两个账号并配置每个路径配置拦截请求资源:
- 账号admin:可以对订单进行增删改查
- 账号userAdd :只能对订单进行查询和添加
配置详情如下:
// Security 配置
@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyAuthenticationFailureHandler failureHandler;
@Autowired
private MyAuthenticationSuccessHandler successHandler;
// 配置认证用户信息和权限
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 添加admin账号
auth.inMemoryAuthentication().withUser("admin").password("123456").
authorities("showOrder","addOrder","updateOrder","deleteOrder");
// 添加userAdd账号
auth.inMemoryAuthentication().withUser("userAdd").password("123456").authorities("showOrder","addOrder");
// 如果想实现动态账号与数据库关联 在该地方改为查询数据库
}
// 配置拦截请求资源
protected void configure(HttpSecurity http) throws Exception {
// 如何权限控制 给每一个请求路径 分配一个权限名称 让后账号只要关联该名称,就可以有访问权限
http.authorizeRequests()
// 配置查询订单权限
.antMatchers("/showOrder").hasAnyAuthority("showOrder")
.antMatchers("/addOrder").hasAnyAuthority("addOrder")
.antMatchers("/login").permitAll()
.antMatchers("/updateOrder").hasAnyAuthority("updateOrder")
.antMatchers("/deleteOrder").hasAnyAuthority("deleteOrder")
.antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login").
successHandler(successHandler).failureHandler(failureHandler)
.and().csrf().disable();
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
2.3 权限不足配置
1.控制器页面请求跳转
@Controller
public class ErrorController {
// 403权限不足页面
@RequestMapping("/error/403")
public String error() {
return "/error/403";
}
}
2.自定义WEB 服务器参数
/**
* 自定义 WEB 服务器参数 可以配置默认错误页面
*/
@Configuration
public class WebServerAutoConfiguration {
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
return factory;
}
}
2.4 认证成功或者失败处理
认证失败接口:AuthenticationFailureHandler
//认证失败
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res, AuthenticationException auth)
throws IOException, ServletException {
System.out.println("登陆失败!");
res.sendRedirect("http://baidu.com");
}
}
认证成功接口:AuthenticationSuccessHandler
// 认证成功
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication arg2)
throws IOException, ServletException {
System.out.println("用户认证成功");
res.sendRedirect("/");
}
}
3. 启动测试
1.浏览器输入:http://localhost:8080,可以由于权限配置,看到自动跳转到了登录界面。 自动跳转到了登录界面:
1.登录页面输入账号admin、密码123456,进入了订单系统 2.点击4个链接,均能访问,因为已经分配所有权限给admin了。
1.登录页面输入账号userAdd、密码123456,进入了订单系统
2.点击查询和添加链接,可以访问。但是删除和修改链接失败,因为代码里没有赋予其权限。