SpringBoot Boot Security的使用

文章目录

  • SpringBoot Boot Security详解
    • 1. Spring Security简介
    • 2. 为什么选择Spring Security
    • 3. SpringBoot Security和Spring Security的关系
    • 4. Spring Boot Security案例
      • 4.1 构建项目依赖
      • 4.2 配置Spring Security
        • 1)配置WebSecurityConfigurerAdapter
        • 2)配置HttpSecurity
      • 4.3 验证权限功能
      • 4.4 通过标签进行权限限制
      • 4.5 从数据库中读取用户的认证信息
        • 1)加入POM依赖
        • 2)配置JPA
        • 3)创建实体类,通过实体类创建数据库表结构。
        • 4)编写数据层,DAO层。
        • 5)编写Service层
        • 6)修改Sercurity配置类
        • 7)启动项目

时间:2020/06/18

作者:Zhang

参考资料:《深入理解SpringCloud与微服务构建》

SpringBoot Boot Security详解

1. Spring Security简介

Spring SecuritySpring Resource社区的一个安全组件。

Spring Security可以在Controller层,Service层,DAO层等以加注解的方式劳保护应用程序的安全。

Spring Security提供了细粒度的权限控制,可以精细到每一个API接口、每一个业务的方法,或者每一个操作数据库的DAO层的方法。

2. 为什么选择Spring Security

选择Spring Security的原因有很多,其中一个重要的原因是对环境的无依赖性,低代码耦合性。将工程重新部署到一个新的服务器上,不需要为Spring Security做什么工作。模块与模块间的耦合性低,模块之间可以自由组合来实现特定的需求的安全功能。

安全方面:Spring Security提供了两个主要的领域。一是“认证”,而是“授权”

为什么选择Spring Security作为微服务开发的安全框架呢?

Apache Shiro在企业及项目开发中十分受欢迎,一般使用在单体服务中。

Spring Security已于应用于SpringBoot项目,也易于集成到采用SpringCloud够早的微服务系统中。

3. SpringBoot Security和Spring Security的关系

在Spring Security框架中,主要包含两个依赖Jar,分别是spring-security-web依赖和spring-security-config依赖,代码如下:

		
            org.springframework.security
            spring-security-web
            5.0.9.RELEASE
        
        
            org.springframework.security
            spring-security-config
            5.0.9.RELEASE
        

SpringBoot Security则对两个jar包进行了封装。spring-boot-starter-security依赖,代码如下:

		
            org.springframework.boot
            spring-boot-starter-security
            2.0.4.RELEASE
        

4. Spring Boot Security案例

4.1 构建项目依赖



    4.0.0

    org.example
    SpringBootSecurityDemo
    1.0-SNAPSHOT

    
        
            org.springframework.boot
            spring-boot-starter-web
            2.0.4.RELEASE
        
        
            org.springframework.boot
            spring-boot-starter-test
            2.0.4.RELEASE
        
        
            org.springframework.boot
            spring-boot-starter-security
            2.0.4.RELEASE
        
    



4.2 配置Spring Security

1)配置WebSecurityConfigurerAdapter

/**
 * 

Title: SecurityConfig

*

Description: * SpringBoot Security 配置类 *

* * @author Zhang * @date 2020/6/18 0027 17:11 */
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启标签 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{ // 设置验证信息 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("1234")) .roles("USER"); auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("zhangsan").password(new BCryptPasswordEncoder().encode("1234")) .roles("VISITOR"); } }

2)配置HttpSecurity

/**
 * 

Title: SecurityConfig

*

Description: * SpringBoot Security 配置类 *

* * @author Zhang * @date 2020/6/18 0027 17:11 */
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启标签 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 配置验证路径信息 /** * 配置需要验证的路径 可以通过HttpMethod.GET添加条件 * 还有其他如: * .antMatchers("/sec/common/**").permitAll() 无条件允许访问 * .anyRequest().authenticated() 所有请求都需要进行验证 */ //.antMatchers("/sec/user/**").authenticated() .antMatchers("/sec/user/**").hasRole("USER") .antMatchers("/sec/common/**").permitAll() .and() /** * 登录表单相关: * .formLogin() //如果参数为空,则采用默认的登录页面 * .formLogin().loginPage("/sec/notLogin") // 自定义登录页面 * .loginProcessingUrl("/login-in") // 自定义登录页面的表单登录提交路径 * .defaultSuccessUrl("/sec/login-success") // 登录成功后跳转 * .failureUrl("/sec/login-error") // 登录失败跳转 */ .formLogin() // .formLogin().loginPage("/sec/notLogin") // 登录页面 没有的话就是采用默认的登录页面 .loginProcessingUrl("/login-in") // 登录表单的action /** * 登录成功跳转: * 登录成功,如果是直接从登录页面登录,会跳转到该URL; * 如果是从其他页面跳转到登录页面,登录后会跳转到原来页面。 * 可设置true来任何时候到跳转 .defaultSuccessUrl("/hello2", true); */ .defaultSuccessUrl("/status/login-success") // 登录成功后跳转 .failureUrl("/status/login-error") // 登录失败跳转 .and() .exceptionHandling().accessDeniedPage("/status/not-login") .and() /** * 设置session策略 */ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .httpBasic().and().csrf().disable(); //post请求需要csrf验证 disable()表示关闭 } }

4.3 验证权限功能

@Controller
@RequestMapping(value = "/sec")
public class MainController {

    @RequestMapping("/user/{id}")
    public void index(@PathVariable String id){
        System.out.println(id);
    }

    @RequestMapping("/user")
    public void test(){
        System.out.println(1);
    }

    @RequestMapping("/login-success")
    @ResponseBody
    public String loginSuccess(){
        System.out.println("登录成功");
        return "登录成功";
    }

    @RequestMapping("/401")
    @ResponseBody
    public String noAccess(){
        System.out.println("无权限");
        return "无权限";
    }

}

4.4 通过标签进行权限限制

首要要在配置类中开启标签的使用。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启标签
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ...
}

再放发前使用:

@PreAuthorize("hasRole('USER')")
@RequestMapping("/user")
public void test(){
    System.out.println(1);
}

4.5 从数据库中读取用户的认证信息

通过使用JPA的方式创建数据库。

1)加入POM依赖


    org.springframework.boot
    spring-boot-starter-data-jpa


    mysql
    mysql-connector-java
    5.1.47

2)配置JPA

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3307/crm?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&serverTimezone=GMT%2B8
    username: root
    password: Shuaizi521.
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

3)创建实体类,通过实体类创建数据库表结构。

User.java

@Entity
public class User implements UserDetails, Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    @Column
    private String password;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    private List<Role> authorities;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public String getPassword() {
        return password;
    }

    public String getUsername() {
        return username;
    }

    public boolean isAccountNonExpired() {
        return true;
    }

    public boolean isAccountNonLocked() {
        return true;
    }

    public boolean isCredentialsNonExpired() {
        return true;
    }

    public boolean isEnabled() {
        return true;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", authorities=" + authorities +
                '}';
    }
}
  • UserDetails接口是SpringSecurity认证信息的核心接口。实现以下方法:
    • getUsername用户名,不一定返回username,也可以是其他用户信息。
    • getAuthorities方法。返回的是该用户的权限信息。权限信息可以是用户的其他信息,不一定是角色信息。
    • 其他方法一般情况下都返回true。

Role.java

@Entity
public class Role implements GrantedAuthority {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return name;
    }

    public String getAuthority() {
        return name;
    }
}

4)编写数据层,DAO层。

@Repository
public interface UserRepo extends JpaRepository<User, Long> {
    /**
     * 根据用户名查询用户信息
     * @param userName 用户名
     * @return
     */
    User findByUsername(String userName);
}

5)编写Service层

编写业务层,这里的业务层实现了UserDetailsService接口,该几口是根绝用户名获取该用户的所有信息,包括用户信息和权限点。

@Service
public class UserService implements UserDetailsService {

    @Autowired
    UserRepo userRepo;

    /**
     * 根据用户名获取该用户的所有信息,包括用户信息和权限点。
     * @param userName 用户名
     * @return
     * @throws UsernameNotFoundException
     */
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        return userRepo.findByUsername(userName);
    }
}

6)修改Sercurity配置类

修改Sercurity配置类,使其数据从数据库中获取。

@EnableWebSecurity
@Configurable
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
//        // 设置验证信息
//        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//                .withUser("admin").password(new BCryptPasswordEncoder().encode("1234"))
//                .roles("USER");
//        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//                .withUser("zhangsan").password(new BCryptPasswordEncoder().encode("1234"))
//                .roles("VISITOR");
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
    ...
}

7)启动项目

启动项目,JPA会连接数据库自动进行建表。

你可能感兴趣的:(权限框架)