Spring Security 在 Spring Boot 中的使用详解【集中式】
1.1 准备
1.1.1 创建 Spring Boot 项目
创建好一个空的 Spring Boot 项目之后,写一个 controller 验证此时是可以直接访问到该控制器的。
1.1.2 引入 Spring Security
在 Spring Boot 中引入 Spring Security 是相当简单的,可以在用脚手架创建项目的时候勾选,也可以创建完毕后在 pom 文件中加入相关依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
引入 Spring Security 后再次访问会发现直接被弹到了登录页面,此时我们还什么都没有配置,为什么 Security 会生效呢,这是因为 Spring Boot 帮我们完成了在 Spring 中需要完成的诸多配置【☞Spring Security 基础入门】。也正是因为 Spring Boot 提供了自动化配置方案,让我们可以“零配置”的使用 Spring Security,所以在 Spring Boot 项目中我们通常使用的安全框架是 Spring Security 而在 Spring 中一般使用 Shiro。
我们并没有配置静态的用户那么该如何登录呢,Spring Boot 为我们提供了一个默认的用户,用户名为:user,密码则是在启动 Spring Boot 项目是随机生成的,我们可以在控制台找到他。
1.2 配置认证
1.2.1 添加静态用户
Spring Boot 除了一些信息写道 yml 配置文件中,其他配置都使用配置类,Spring Security 需要继承 WebSecurityConfigurerAdapter
,配置用户信息需要重写 configure(AuthenticationManagerBuilder auth)
方法。配置完毕后,将不会再使用 user 用户。
/** * Created with IntelliJ IDEA. * * @author Demo_Null * @date 2020/10/18 * @description Spring Security 配置类 */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 配置静态用户 auth.inMemoryAuthentication() .withUser("admin") .password("{noop}123") // 此处需要加 {noop} 表示该密码为明文 .roles("USER"); } }
1.2.2 添加数据库认证 ☞ 添加用户实体类
Spring Security 中使用的用户是 UserDetails,我们要么让自定义用户类实现 UserDetails,要么使用时将自定义用户类转换为 UserDetails。建议实现 UserDetails。因为该类中涉及到角色信息所以我们还需要创建角色类。我们在以后的操作中可能会将对象转为 json 或者将 json 转为对象,所以我们重写的方法需要加上 @JsonIgnore
将其忽略(该类本来就需要的不用忽略)。
/** * Created with IntelliJ IDEA. * * @author gaohu9712@163.com * @date 2020/10/18 * @description 用户实体类 */ public class SysUser implements UserDetails { private Long id; private String username; private String passwrod; private List<SysRole> roleList = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPasswrod(String passwrod) { this.passwrod = passwrod; } public List<SysRole> getRoleList() { return roleList; } public void setRoleList(List<SysRole> roleList) { this.roleList = roleList; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return roleList; } @Override public String getPassword() { return passwrod; } @Override public String getUsername() { return username; } @Override @JsonIgnore public boolean isAccountNonExpired() { return false; } @Override @JsonIgnore public boolean isAccountNonLocked() { return false; } @Override @JsonIgnore public boolean isCredentialsNonExpired() { return false; } @Override @JsonIgnore public boolean isEnabled() { return false; } }
☞ 创建角色类
Spring Security 中使用的角色信息使用的是 GrantedAuthority 所以我们的角色类也需要实现 GrantedAuthority。
/** * Created with IntelliJ IDEA. * * @author Demo_Null * @date 2020/10/18 * @description 角色类 */ public class SysRole implements GrantedAuthority { private Long id; private String roleName; private String roleDesc; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } @Override @JsonIgnore public String getAuthority() { return roleName; } }
☞ 添加持久层
此处省略使用通用 mapper 操作数据库的内容【☞ Mybatis 使用通用 mapper】,jpa 等其他操作数据库的方法亦可。
☞ 认证类
Spring Boot 中 Spring Security 的认证类与 Spring 中的并无区别,都需要实现 UserDetailsService 接口,然后重写 loadUserByUsername(String s)
方法并返回一个 UserDetails。
/** * Created with IntelliJ IDEA. * * @author Demo_Null * @date 2020/10/18 * @description 认证类 */ public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { return userMapper.findByName(s); } }
☞ 配置类
/** * Created with IntelliJ IDEA. * * @author Demo_Null * @date 2020/10/18 * @description Spring Security 配置类 */ @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean // BCrypt 交由 Ioc 容器管理 public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 认证类 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } }
1.3 授权
1.3.1 开启方法级授权
在启动类上使用 @EnableGlobalMethodSecurity
注解开启方法级授权。参数 prePostEnabled 代表 Spring 中的权限控制注解;securedEnabled 代表 Spring Security 中的权限控制注解; jsr250Enabled 代表 jsr250 的权限控制注解
。
@SpringBootApplication @MapperScan("com.software.springsecurity.mapper") @EnableGlobalMethodSecurity(securedEnabled = true) public class SpringSecurityApplication { public static void main(String[] args) { SpringApplication.run(SpringSecurityApplication.class, args); } }
1.3.2 添加方法权限
当用户仅有 ROLE_USER
权限时仅能访问 findStr 方法而不能访问 get 方法;要想访问 get 方法用户必须具有 ROLE_ADMIN
权限。
/** * Created with IntelliJ IDEA. * * @author Demo_Null * @date 2020/10/18 * @description */ @RestController @RequestMapping("/demo") public class DemoController { @GetMapping("/find") @Secured("ROLE_USER") public String findStr() { return "请求成功"; } @GetMapping("/get") @Secured("ROLE_ADMIN") public String get() { return "get"; } }
1.3.3 异常拦截页面
@ControllerAdvice public class HandlerControllerAdvice { @ExceptionHandler(AccessDeniedException.class) public String handlerException(){ return "redirect:/403.html"; } @ExceptionHandler(RuntimeException.class) public String runtimeHandlerException(){ return "redirect:/500.html"; } }
总结
到此这篇关于Spring Security 在 Spring Boot 中的使用详解【集中式】的文章就介绍到这了,更多相关Spring Security 在 Spring Boot使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!