spring security基本概念及实际应用

1、认证授权基本概念

1.1、什么是认证

认证就是校验一个用户是否合法,是否是存在的用户。

1.2、什么是授权

一些资源需要用户有指定的权限才可以访问。

1.3、什么是会话

用户登录成功后,为了避免后续用户的每次操作都再一次进行认证,把用户的信息储存起来。

1.4、授权的数据模型

授权可以理解为who对what进行how操作
who:用户或者程序
what:资源
how:权限
可以分成6张表

1.5、RBAC

访问控制分为两种:

  • 基于角色的访问控制(Role-Based Access Control)
  • 基于资源的访问控制(Resource-Based Access Control)

2、使用SpringBoot继承Spring Security

首先创建SpringBoot项目,引入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

编写配置类

@Configuration
@EnableWebSecurity//启用Spring Security
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	//为用户建立内存用户存储
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        UserDetails user =
                User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();

        return new InMemoryUserDetailsManager(user);
    }
	//定义密码比对器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();// 不对密码进行加密
    }

	//核心配置,定义Spring Security如何对请求进行拦截
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()// 开始对请求进行处理
                    .antMatchers("/r/r1").hasAuthority("p1")// /r/r1请求必须有p1权限
                    .antMatchers("/r/r2").hasAuthority("p2")// /r/r2请求必须有p2权限
                    .antMatchers("/r/**").permitAll()// 后续/r/**请求全部放行
                    .antMatchers("/", "/home").permitAll()// /、/home不需要认证
                    .anyRequest().authenticated()// 其他所有请求都需要认证
                    .and()
                .formLogin()
                    .loginPage("/login")// 指定登录页
                    .permitAll()
                    .and()
                .logout()// 注销请求全部放行
                    .permitAll();
    }
}

userDetailsService()方法直接在内存中定义了一个用户,但是大多数时候都希望从其他地方获取到用户。这时候可以定义一个UserDetailService的实现类,实现loadUserByUsername方法,在其中定义用户的验证规则。

@Service
public class SpringDataUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username: " + username);
        UserDetails userDetails = User.withUsername(username).password("$2a$10$unG4fq1zoSukMWA1Ie/U2.PG1WUHO5h6ai7aVWN59dk3CPdQgZnAm").authorities("p1").build();
        return userDetails;
    }
}

可以注入dao让其去数据库验证用户的有效性。

那么如果现在用户认证成功了,会话功能如何体现呢?
用户认证成功后,会把用户的相关信息存在Security上下文中,可以通过SecurityContextHolder.getContext().getAuthentication()获取到用户的信息。

/**
     * 获取当前登录用户名
     */
    public String getUsername(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 如果没有认证返回null
        if (!authentication.isAuthenticated()){
            return null;
        }
        Object principal = authentication.getPrincipal();
        String username = null;
        if (principal instanceof UserDetails){
            username = ((UserDetails)principal).getUsername();
        } else {
            username = principal.toString();
        }
        return username;
    }

对资源拦截可以分成web拦截和方法层面的拦截。
现在是web拦截

.antMatchers("/r/r1").hasAuthority("p1")// /r/r1请求必须有p1权限
.antMatchers("/r/r2").hasAuthority("p2")// /r/r2请求必须有p2权限

在配置类上定义@EnableGlobalMethodSecurity可以启用方法拦截注解功能
比如可以加上如下配置

@EnableGlobalMethodSecurity(prePostEnabled = true)

在方法中加上

@PreAuthorize("hasAuthority('p1')")

那么在访问此方法时要求用户有p1权限

posted @ 2020-10-22 19:24  luotuoccc  阅读(188)  评论(0)    收藏  举报