- springBoot整合spring security(环境为2
- SpringBoot +Spring Security + th
- Spring-Security配合OAuth2初探
- Shiro、Spring Security整合
- 整合springboot + security + druid
- SpringBoot security 整合 OAuth2
- 27.OAuth2.0-Spring Cloud Securit
- springboot+vue集成mavon-editor,开发在
- 2022-05-16 Springboot 系列 (8) - S
- 2022-05-18 Springboot 系列 (9) - S
导入依赖
<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>
创建一个 HelloController:
@RestController
public class HelloController {
@GetMapping("/he")
public String he() {
return "hello Security";
}
}
访问http://localhost:8081/he
当用户从浏览器发送请求访问 /he接口时,客户端重定向到 /login 页面,用户在 /login 页面登录,登陆成功之后,就会自动跳转到 /he接口。
输入用户名和密码,用户名默认为user,密码会打印在控制台上
image.png image.png
image.png
这个随机生成的密码,每次启动时都会变。对登录的用户名/密码进行配置,有三种不同的方式:
在 application.properties或者application.yml 中进行配置
通过 Java 代码配置在内存中
通过 Java 从数据库中加载(下一篇博文介绍)
配置文件配置用户名/密码
properties
spring.security.user.name=admin
spring.security.user.password=123
yml
spring:
security:
user:
name: admin
password: 123
roles:
- admin
Java 配置用户名/密码
创建一个 Spring Security 的配置类,继承 WebSecurityConfigurerAdapter 类
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class SecurityConfig<V> extends WebSecurityConfigurerAdapter{
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("$2a$10$5cfZHg5x9jRNPSHrVnPSE.YEcoqQkfO5IlpxY1R1Jo3u.1JsZPoiW")
.roles("admin") //123
.and()
.withUser("user").password("$2a$10$TawHx0DjM.trtcCdKumH0uCLqNF7UQVmNbAXi/NXYzv0GDQ6YOU8i")
.roles("user"); //123
}
}
public static void main(String[] args) {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("123"));
System.out.println(bCryptPasswordEncoder.encode("123"));
}
这里我们在 configure 方法中配置了两个用户,用户的密码都是加密之后的字符串(明文是 123),从 Spring5 开始,强制要求密码要加密,如果非不想加密,可以使用一个过期的 PasswordEncoder 的实例 NoOpPasswordEncoder,但是不建议这么做,毕竟不安全。
image.png
登录配置
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //开启配置
.antMatchers("/admin/**").hasRole("admin") //访问/admin/**下的路径,必须具备admin身份
.antMatchers("/user/**").hasAnyRole("admin","user") //访问/user/**下的路径,必须具备admin和user中其中一个身份
.antMatchers("/db/**").access("hasAnyRole('admin','user')") //访问/db/**下的路径,必须具备admin和user中其中一个身份
.anyRequest() //其他请求
.authenticated() //已验证 也就是其他请求只需要登录就能访问
.and()
.formLogin() //表单登录
.loginProcessingUrl("/doLogin") //登录接口 如果要用postmall测试
.loginPage("/login1") //登录页面
.usernameParameter("uname") //自定义登录key 默认为 username
.passwordParameter("upwd") //自定义登录key 默认为 password
.successHandler(new AuthenticationSuccessHandler() { //登录成功处理 直接返回json
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res,
Authentication authentication) throws IOException, ServletException {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
HashMap<String, Object> map = new HashMap<String, Object>();
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();
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("status", 200);
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 request, HttpServletResponse res, Authentication authentication)
throws IOException, ServletException {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("status", 200);
map.put("msg", "注销成功");
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
}
})
.and()
.csrf().disable(); // 关闭csrf 以便我们在 postman类似的软件测试被系统给拦截了
}
}
如果不是前后端分离项目,
登录成功:使用.successForwardUrl("/index") //登录成功跳转地址
image.png
登录失败:
image.png
controller层添加一些接口以便我们测试
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/he")
public String he() {
return "hello Security";
}
@GetMapping("/admin/he")
public String admin() {
return "hello admin";
}
@GetMapping("/user/he")
public String user() {
return "hello user";
}
@GetMapping("/db/he")
public String db() {
return "hello db";
}
@GetMapping("/login1")
public String login1() {
return "hello login1";
}
}
通过postman调用:localhost:8081/he,来到登录页,因为没有进行登录
image.png
调用:localhost:8081/doLogin 登录user账户
image.png再次调用:localhost:8081/he
image.png
调用:localhost:8081/admin/he(没有权限)
image.png
调用:localhost:8081/user/he
image.png
调用:localhost:8081/db/he
image.png
登录admin账户
image.png
调用:localhost:8081/admin/he
image.png
对方法进行保护
要开启Spring方法级安全,在添加了@Configuration注解的类上再添加@EnableGlobalMethodSecurity注解即可
image.png
@EnableGlobalMethodSecurity(prePostEnabled = true)
创建Service层添加测试方法
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
@PreAuthorize("hasRole('admin')") //拥有admin权限
public String admin() {
return "hell admin";
}
@PreAuthorize("hasRole('user')") //拥有user权限
public String user() {
return "hell user";
}
@PreAuthorize("hasAnyRole('admin','user')") //拥有admin权限和user权限其中一个
public String db() {
return "hell db";
}
}
Controller层也提供几个登录就可以访问方法
@Autowired
HelloService helloService;
@GetMapping("/helloAdmin")
public String helloAdmin() {
return helloService.admin();
}
@GetMapping("/helloUser")
public String helloUser() {
return helloService.user();
}
@GetMapping("/hellodb")
public String hellodb() {
return helloService.db();
}
登录user账户调用:localhost:8081/helloUser(可以调用)
调用:localhost:8081/hellodb(可以调用)
image.png
调用:localhost:8081/helloAdmin(不可以调用,没有权限)
image.png
登录admin账户调用:localhost:8081/helloAdmin(可以调用)
image.png
调用:localhost:8081/hellodb(可以调用)
image.png
调用:localhost:8081/helloUser(不可以调用,没有权限)
image.png
@EnableGlobalMethodSecurity注解详细说明推荐:https://www.jianshu.com/p/77b4835b6e8e
网友评论