Spring Security 在 Spring Boot 中的使用详解【集中式】

网友投稿 268 2022-11-17


Spring Security 在 Spring Boot 中的使用详解【集中式】

1.1 准备

1.1.1 创建 Spring Boot 项目

创建好一个空的 Spring Boot 项目之后,写一个 controller 验证此时是可以直接访问到该控制器的。

1.1.2 引入 Spring Security

在 Spring Boot 中引入 Spring Security 是相当简单的,可以在用脚手架创建项目的时候勾选,也可以创建完毕后在 pom 文件中加入相关依赖。

org.springframework.boot

spring-boot-starter-security

引入 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 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 getRoleList() {

return roleList;

}

public void setRoleList(List 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.

*

* @authoCMKegr 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";

}

}

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java信号量Semaphore原理及代码实例
下一篇:在springboot中实现个别bean懒加载的操作
相关文章

 发表评论

暂时没有评论,来抢沙发吧~