Spring Security 基本使用

相关

Shiro基本使用

一、Spring Security是什么?

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。

Spring Security 和 Shiro 一样都是安全框架,Shiro是apache的产品,Spring Security 是Spring全家桶的成员。现在SpringBoot是主要潮流,Spring Security 能更好的结合使用。 当然两个产品都有优劣势,具体技术选型还是得看企业各自的应用场景。

二、认证和授权

和Shiro大同小异,都是Authentication(身份认证)和Authorization(授权),简单的来说就是:

  1. 证明我是谁,我是不是合法用户
  2. 认证成功后,我能做什么事

1.准备

基于springboot讲解,所以先创建一个springboot项目,然后再在pom.xml里引入web 和 security 的依赖

<dependencies>
    <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>
</dependencies>

创建一个测试类TestController.java

@RestController
public class TestController {

    @RequestMapping(value = "hello", method = RequestMethod.GET)
    public String hello() {
        return "hello world";
    }
}

2.认证

在未引入security的依赖时,访问 http://localhost:8080/hello,正常返回
在这里插入图片描述
引入security的依赖,再去访问时,则会跳转到一个登陆表单页面,说明security起作用。
在这里插入图片描述

仅仅只是引入依赖,默认的用户名和密码又是多少??

当我们在项目配置文件没有配置属性的时候,默认的用户名是 user 密码则是UUID生成的随机字符串,在项目启动的时候会打印在控制台的日志上。
在这里插入图片描述

可以看到密码是由UserDetailsServiceAutoConfiguration这个类打印的.这个类有一个@Bean 实例了一个InMemoryUserDetailsManager类,其中一个参数是SecurityProperties

@Bean
@ConditionalOnMissingBean(
    type = {"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository"}
)
@Lazy
public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties, ObjectProvider<PasswordEncoder> passwordEncoder) {
    User user = properties.getUser();
    List<String> roles = user.getRoles();
    return new InMemoryUserDetailsManager(new UserDetails[]{org.springframework.security.core.userdetails.User.withUsername(user.getName()).password(this.getOrDeducePassword(user, (PasswordEncoder)passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build()});
}

private String getOrDeducePassword(User user, PasswordEncoder encoder) {
    String password = user.getPassword();
    if (user.isPasswordGenerated()) {
        logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
    }

    return encoder == null && !PASSWORD_ALGORITHM_PATTERN.matcher(password).matches() ? "{noop}" + password : password;
}

找到security自动配置的配置文件类 SecurityProperties.java, 可以看到 spring.security的相关配置会被注入进来,
在这里插入图片描述

2.1 设置用户名密码

修改默认密码的方式有3种

  1. 在项目配置文件如application.properties里进行配置
# 用户名
spring.security.user.name=
# 密码
spring.security.user.password=
  1. 通过配置类进行配置,这里新建一个SecurityConfig.java 继承 WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("------HttpSecurity http------");
        super.configure(http);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("------AuthenticationManagerBuilder auth------");
        super.configure(auth);
    }
}

@Configuration@EnableWebSecurity 两个注解让spring security配置生效。
这里两个父类的方法
configure(HttpSecurity http):http request的相关配置

  • formLogin():表单登陆支持
  • httpBasic():配置Http Basic验证
  • cors():配置跨域
  • sessionManagement():session配置
  • authorizeRequests():访问授权配置
  • csrf():添加 CSRF 支持
  • addFilterBefore():添加过滤器在指定过滤器前
  • addFilterAt():添加过滤器替换指定过滤器
  • addFilterAfter():添加过滤器在指定过滤器后
  • logout():添加退出登录支持
  • 等等。。。。

configure(AuthenticationManagerBuilder auth):认证相关配置 密码也是在这边配置

代码示例:

	@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("------AuthenticationManagerBuilder auth------");
        auth.inMemoryAuthentication().withUser("admin").password(new BCryptPasswordEncoder().encode("123456"));
    }

    /**
     * 配置security的加密方式
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    

密码加密方式这个是要配置的,否则会报错。

  1. 自定义实现类,通常实际项目的用户名和密码都是在数据库存储,进行认证需要与数据库交互,与下面的认证流程一起讲解。
2.2 认证流程

在没有自定义实现认证登陆,默认的登陆表单提交调用UsernamePasswordAuthenticationFilter类的attemptAuthentication(HttpServletRequest request, HttpServletResponse response)方法
在这里插入图片描述
然后调用的是DaoAuthenticationProvider
在这里插入图片描述

最后UserDetailsService类返回一个 UserDetails 对象
在这里插入图片描述
在这里插入图片描述
也就是说我们可以自定义类继承UserDetailsService然后重写 loadUserByUsername() 方法,获取数据库用户名/密码进行登陆的校验!

实现步骤:

  • 创建一个类实现userDetailsService重写接口,返回一个user,这里就可以设置用户名/密码
    在这里插入图片描述
  • SecurityConfig类里面配置UserDetailsService
	@Autowired
    private UserDetailsService userDetailsService;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("------AuthenticationManagerBuilder auth------");
        auth.userDetailsService(userDetailsService);
    }

就是这么简单!

	@Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
		// 实际项目,可以在这里与数据库进行交互,未找到用户可以抛出UsernameNotFoundException
		// 用户名存在,返回一个user交给security进行密码校验
        return null
    }

3. 授权

太累了。。。以后再写!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值