转载

Spring Security简单起步(使用Spring Boot)

创建一个SpringBoot项目

  • 网址输入 start.spring.io https://start.spring.io/
  • 输入Group 和 Artifact
  • 点击下面一排小字的 Switch to the full version.
  • 勾选 Security 和 Web俩个模块
  • 如图所示:
  • 找到项目中包下的 XXXApplication的那个java类, 为它填上三个注解
//相当于三个注解,以后再讲
        @SpringBootApplication
        //相当于ResponseBody 和 Controller 
        @RestController
        //在这个类中所使用的jar包都会被加载,而且提供默认配置 excludeName可以取消默认配置
        @EnableAutoConfiguration
  • 现在在这个类里面添加一个方法
@RequestMapping("/")
        public String home(){
            return "MackyHuang First SpringBoot";
        }
  • 然后打开pom.xml,备注里面关于tomcat的代码
<!--<dependency>-->
            <!--<groupId>org.springframework.boot</groupId>-->
            <!--<artifactId>spring-boot-starter-tomcat</artifactId>-->
            <!--<scope>provided</scope>-->
        <!--</dependency>-->
  • 允许这个 XXXApplication类的main方法,我们就会看到springboot启动啦!

关于SpringSecurity的配置与使用

  • 新建一个Config类 继承WebSecurityConfigurerAdapter,然后实现里面的三个方法,先简略的看一下代码再进行解释
@Configuration
        @EnableWebSecurity
        public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
        @Resource
        private UserServiceOwn serviceOwn;
        @Override
        protected void configure(HttpSecurity http) throws Exception {
        //允许主目录 / 的访问
        //check任何目录
        //允许注销
        //允许表单登陆
        //禁用csrf
        http.authorizeRequests()
        .antMatchers("/authorize", "/").permitAll()
        .anyRequest().authenticated()
        .and()
        .logout().permitAll()
        .and()
        .formLogin();
        http.csrf().disable();
        }
        
        //允许资源文件加载
        @Override
        public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
        }
        
        //Spring Security中密码的存储格式需要加密,所以需要这种格式
        //如果再数据库中
        //需要
        //auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("macky")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("ADMIN");
        
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("huang")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("ADMIN");
        
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("user")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("USER");
        
        //auth.userDetailsService(serviceOwn).passwordEncoder(new PasswordEncoderOwn());
        ////security默认的数据库操作
        //auth.jdbcAuthentication().usersByUsernameQuery("macky").authoritiesByUsernameQuery("admin").passwordEncoder(new BCryptPasswordEncoder());
        }
        }
  • 在看完代码以及注释以后(其实注释已经说明了大量的问题)
  • 第一个类
@Override
        protected void configure(HttpSecurity http) throws Exception {
    
        http.authorizeRequests()  
        .antMatchers("/authorize", "/").permitAll()  //允许主目录 / 的访问
        .anyRequest().authenticated() //check任何目录
        .and()
        .logout().permitAll()  //允许注销
        .and()  
        .formLogin();  //允许表单登陆
        http.csrf().disable();   //禁用csrf
        }
  • 这里 调用http, 进行了一系列匹配, 其中的csrf就是Cross-site request forgery跨站请求伪造
  • 第二个类
//    允许资源文件加载
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
        }
  • 这个类解决的是资源文件的,对于那些请求这些资源文件的请求进行忽略
  • 第三个类
//这里只介绍关于内存中的储存用户信息
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //Spring Security中密码的存储格式需要加密,所以需要这种格式
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("macky")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("ADMIN");
        
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("huang")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("ADMIN");
        
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
        .withUser("user")
        .password(new BCryptPasswordEncoder().encode("123456"))
        .roles("USER");

        。。其实以上的内容,就是内存中创建一个用户信息,指定气密码的匹配器,然后指定用户名,密码和角色,这里我们创建了3个用户,俩个角色

        
        //auth.userDetailsService(serviceOwn).passwordEncoder(new PasswordEncoderOwn());
        ////security默认的数据库操作
        //auth.jdbcAuthentication().usersByUsernameQuery("macky").authoritiesByUsernameQuery("admin").passwordEncoder(new BCryptPasswordEncoder());
    }

搞定了用户角色层次的,现在我们来配置一些访问的网页把(以下代码都在XXXApplication中,这里我们其实是把它当作是一个Controller,因为注解里面已经将它进行了配置)

@RequestMapping("/hello")
    public String hello(){
        return "hello world";
    }
  • 现在,让我们再允许一次项目,访问主目录 / 和 /hello 俩个页面,会发现, 主目录顺利访问了,然而,那个hello页面跳转到了登陆界面,这是为了啥子呢!
  • 回想我们前面的配置,会发现,我们在第一个config里面忽略了主目录的过滤,所有它是不需要验证的。

让我们试试角色把

@PreAuthorize("hasRole('ROLE_ADMIN')")
    @RequestMapping("/manage")
    public String manage(){
        return "Only admin can see this page";
    }
  • 并且!在XXXApplication类上面添加注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
  • 添加了这段代码以后,继续访问,试着用不同的账号去登陆,然后查看结果
  • 拥有ADMIN角色的用户可以顺利访问,而拥有USER的用户出现没有权限访问的页面,返回403 无权限访问
  • 很明显,一来我们添加了俩个注解
    @PreAuthorize("hasRole('ROLE_ADMIN')")
  • 它使得我们的方法在访问前需要进行一定的操作,而我们在里面的参数是 hasRole,所有就是判断访问者的角色,而另外一个 @EnableGlobalMethodSecurity 就是使得上面的这个注解生效

让我们了解更多一些

  • 其实类似于 @PreAuthorize 这样的注解不止这一个

    //    这是方法进入前的判断,可以有内置的方法,也可以对参数进行判断
       @PreAuthorize("#index<10")    
       //    拦截方法调用后  这里还是遭到了拦截
       @PostAuthorize("returnObject==2")
    
       //    如果参数或者返回值是集合的时候,就可以使用*Filter注解,功能和上面的是一样的
       //    filterObject表示集合内的一个元素
       @PreFilter("filterObject<10")
       @PostFilter("filterObject<5")
  • 这俩组注解其实见文知意, 类似于AOP里面的方法处理前后的判断

博文是作者原本在其他平台的,现迁移过来

原文  https://segmentfault.com/a/1190000021352272
正文到此结束
Loading...