- Spring Security 教程
- 1、介绍
- 1.1、特性
- 1.2、配置
- 1.2.1、POM.XML 文件配置
- 1.2.2、application.yml 文件配置
- 1.2.3、config
- 1.2.4、controller
- 2、注解配置
1.1、特性Spring Security是一个强大的、高度可定制的身份验证和访问控制框架。它是保护基于spring的应用程序的事实上的标准。
Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正强大之处在于它可以很容易地扩展以满足定制需求。
它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
- 身份验证(确定你是谁)
- 授权(确定你能做什么)
- 针对常见漏洞的保护的全面支持(保护你)
- pom.xml
- application.yml
- config层
- controller层
1.2.2、application.yml 文件配置org.springframework.boot spring-boot-starter-security org.springframework.security spring-security-test test org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test
server: port: 8888 #配置文件中配置Spring Security 默认 Username : user #spring: # security: # user: # name: admin # password: admin123 # roles: user1.2.3、config
package com.shiqi.springsecurity.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
//单个config配置
//@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//配置编码
//@Bean
//PasswordEncoder passwordEncoder(){
// return NoOpPasswordEncoder.getInstance();
//}
//不管是在配置文件中配置,还是在yml文件中配置。这种配置都是写死的,我们还是要在数据库种配置
//从 Spring5 开始密码是一定要加密的,不加密直接运行是有问题的
//@Override
//protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication()
// .withUser("shiqi").password("123").roles("admin")
// .and()
// .withUser("yaoer").password("321").roles("user");
//}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasAnyRole("admin","user")
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.loginPage("/login")
//登录成功的处理
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Map map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
out.write(new ObjectMapper().writevalueAsString(map));
out.flush();
out.close();
}
})
//登录失败的处理
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
resp.setContentType("application/json; charset=UTF-8");
PrintWriter out = resp.getWriter();
Map map = new HashMap<>();
map.put("status",500);
if(e instanceof LockedException){
map.put("msg","账户被锁定,登陆失败");
}else if(e instanceof BadCredentialsException){
map.put("msg","用户名或密码输入错误,登陆失败");
}else if(e instanceof DisabledException){
map.put("msg","用户被禁用,登陆失败");
}else if(e instanceof AccountExpiredException){
map.put("msg","用户过期,登陆失败");
}else if(e instanceof CredentialsExpiredException){
map.put("msg","密码过期,登录失败");
}else {
map.put("msg","登陆失败");
}
out.write(new ObjectMapper().writevalueAsString(map));
out.flush();
out.close();
}
})
.permitAll()
.and()
//注销登录
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json; charset=UTF-8");
PrintWriter out = resp.getWriter();
Map map = new HashMap<>();
map.put("status", 200);
map.put("msg", "Spring Security 注销成功");
out.write(new ObjectMapper().writevalueAsString(map));
out.flush();
out.close();
}
})
.and()
.csrf().disable();
}
}
1.2.4、controller
package com.shiqi.springsecurity.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("hello")
public String hello(){
return "hello Spring Security";
}
@GetMapping("/admin/hello")
public String helloAdmin(){
return "hell Spring Security admin";
}
@GetMapping("/user/hello")
public String helloUser(){
return "hell Spring Security user";
}
@GetMapping("/login")
public String login(){
return "hell Spring Security please login";
}
}
2、注解配置
- http.authorizeRequests() : 授权请求;该配置是要求应用中所有url的访问都需要进行验证。我们也可以自定义哪些URL需要权限验证,哪些不需要。该方法有很多子方法,每个子匹配器将会按照声明的顺序起作用。
- antMatcher(" /admin/** "): ant匹配器 ;过滤掉 /admin/xxx 这样的访问url路径
- hasRole(“admin”) :角色授权:授权代码,给角色为admin的用户提供授权
- antMatcher(" /admin/** ").hasRole(“admin”) :意思是,请求路径满足 /admin/** 格式,则用户需要具备 admin 角色。
- anyRequest():表示所有匹配的请求
- authenticated():允许认证的用户进行访问
- anyRequest().authenticated():剩余的其他格式的请求路径,只需要认证(登录)后就可以访问。
- and():可以认为 and() 是将方法链接在一起的一种方式
- loginPage("/login.html")//用户未登录时,访问任何资源都转跳到该路径,即登录页面
- loginProcessingUrl("/login")//登录表单form中action的地址,也就是处理认证请求的路径
- permitAll():相当允许该路径通过
- csrf().disable():取消csrf防护



