zoukankan      html  css  js  c++  java
  • 吴裕雄天生自然Spring BootSpring Security

        Spring Security是一个专门针对Sping应用系统的安全框架,充分利用了Spring框架的依赖注入和AOP功能,为Spring应用系统提供安全访问控制解决方案。
        在Spring Security安全框架中,有两个重要概念,即授权(Authorization)和认证(Authentication)。授权即确定用户在当前应用系统下所拥有的功能权限;认证即确认用户访问当前系统的身份。
    Spring Security的适配器
    
        Spring Security为Web应用提供了一个适配器类WebSecurityConfigurerAdapter,该类实现了WebSecurityConfigurer<WebSecurity>接口,并提供了两个configure方法用于认证和授权操作。
        开发者创建自己的Spring Security适配器类是非常简单的,只需要定义一个继承WebSecurityConfigurerAdapter的类,并在该类中使用@Configuration注解,就可以通过重写两个configure方法来配置所需要的安全配置。
    @Configuration
    public class MySecurityConfigurerAdapter extends WebSecurityConfigurerAdapter{
    /**
         * 用户认证
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        }
        /**
         * 请求授权
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
        }
    }
    Spring Security的用户认证
    
        在Spring Security的适配器类中,通过重写configure(AuthenticationManagerBuilder auth)方法完成用户认证。
    
    
    1.内存中的用户认证
    
    2.通用的用户认证
    内存中的用户认证
    
        使用AuthenticationManagerBuilder的inMemoryAuthentication()方法可以添加在内存中的用户,并给用户指定角色权限。示例代码如下:
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("chenheng").password("123456").roles("ADMIN","DBA");        auth.inMemoryAuthentication().withUser("zhangsan").password("123456").roles("USER");
        }
    
    上述示例代码中添加了两个用户,一个是用户名为“chenheng”,密码为“123456”,用户权限为“ROLE_ADMIN”和“ROLE_DBA”;一个是用户名为“zhangsan”,密码为“123456”,用户权限为“ROLE_USER”。“ROLE_”是Spring Security保存用户权限的时候,默认加上。
    通用的用户认证
    
        我们在实际应用中,可以查询数据库获取用户和权限,这时我们需要自定义实现org.springframework.security.core.userdetails.UserDetailsService接口的类,并重写public UserDetails loadUserByUsername(String username)方法查询对应的用户和权限,然后注册Service类完成用户认证。
    Spring Security的请求授权
    
    在Spring Security的适配器类中,通过重写configure(HttpSecurity http)方法完成用户授权。在configure(HttpSecurity http)方法中,使用HttpSecurity的authorizeRequests()方法的子节点给指定用户授权访问URL模式。我们可以通过antMatchers方法使用Ant风格匹配URL路径。匹配请求路径后,可以针对当前用户对请求进行安全处理。

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
            //首页、登录、注册页面、登录注册功能、以及静态资源过滤掉,即可任意访问
            .antMatchers("/toLogin", "/toRegister", "/", "/login", "/register", "/css/**", "/fonts/**", "/js/**").permitAll()
            //这里默认追加ROLE_,/user/**是控制器的请求匹配路径
            .antMatchers("/user/**").hasRole("USER")
            .antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA")
            //其他所有请求登录后才能访问
            .anyRequest().authenticated()
            .and()
            //将输入的用户名与密码和授权的进行比较
            .formLogin()
                .loginPage("/login").successHandler(myAuthenticationSuccessHandler)
                .usernameParameter("username").passwordParameter("password")
                //登录失败
                .failureUrl("/login?error")
            .and()
            //注销行为可任意访问
            .logout().permitAll()
            .and()
            //指定异常处理页面
            .exceptionHandling().accessDeniedPage("/deniedAccess");
        }
    http.authorizeRequests():开始进行请求权限设置。
    antMatchers("/toLogin", "/toRegister", "/", "/login", "/register", "/css/**", "/fonts/**", "/js/**").permitAll():“/toLogin”、“/toRegister”、“/”、“/login”、“/register”等请求以及静态资源过滤掉,即任意用户可访问。
    antMatchers("/user/**").hasRole("USER"):请求匹配“/user/**”,拥有“ROLE_USER”角色的用户可访问。
    antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA"):请求匹配“/admin/**”,拥有“ROLE_ADMIN”或“ROLE_DBA”角色的用户可访问。
    anyRequest().authenticated():其余所有请求都需要认证(用户登录后)才可访问。formLogin():开始设置登录操作。loginPage("/login").successHandler(myAuthenticationSuccessHandler):设置登录的访问地址以及登录成功处理操作。
    usernameParameter("username").passwordParameter("password"):登录时接收参数username的值作为用户名,接收参数password的值作为密码。
    failureUrl("/login?error"):指定登录失败后转向的页面和传递的参数。
    logout().permitAll():注销操作,所有用户均可访问。
    exceptionHandling().accessDeniedPage("/deniedAccess"):指定异常处理页面。
    Spring Security的核心类
    
        Spring Security的核心类包括Authentication、DaoAuthenticationProvider、GrantedAuthority、PasswordEncoder、SecurityContextHolder、UserDetails和UserDetailsService。
    1.Authentication
    
        Authentication用来封装用户认证信息的接口,在用户登录认证之前,Spring Security将相关信息封装为一个Authentication具体实现类的对象,在登录认证成功后将生成一个信息更全面、包含用户权限等信息的Authentication对象,然后将该对象保存在SecurityContextHolder所持有的SecurityContext中,方便后续程序进行调用,如当前用户名、访问权限等。
    SecurityContextHolder
    
    SecurityContextHolder顾名思义是用来持有SecurityContext的类。SecurityContext中包含当前认证用户的详细信息。Spring Security使用一个Authentication对象描述当前用户的相关信息。例如,最常见的是获得当前登录用户的用户名和权限。
    //获得当前用户名称
    SecurityContextHolder.getContext().getAuthentication().getName();
    //获得当前用户权限
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    List<String> roles = new ArrayList<String>();
    for (GrantedAuthority ga : authentication.getAuthorities()) {
        roles.add(ga.getAuthority());
    }
    3.UserDetails
    
        UserDetails是Spring Security的一个核心接口。该接口定义了一些可以获取用户名、密码、权限等与认证相关的信息的方法。通常需要在应用中获取当前用户的其他信息,如Email、电话等。这时只包含认证相关的UserDetails对象可能就不能满足我们的需要了。我们可以实现自己的UserDetails,在该实现类中定义一些获取用户其他信息的方法,这样我们就可以直接从当前SecurityContext的Authentication的principal中获取用户的其他信息。
        Authentication.getPrincipal()的返回类型是Object,但通常返回的其实是一个UserDetails的实例,通过强制类型转换可以将Object转换为UserDetails类型。
    4.UserDetailsService
    
        UserDetails是通过UserDetailsService的loadUserByUsername(String username)方法加载的。UserDetailsService也是一个接口,也需要实现自己的UserDetailsService来加载自定义的UserDetails信息。
        登录认证时,Spring Security将通过UserDetailsService的loadUserByUsername(String username)方法获取对应的UserDetails进行认证,认证通过后将该UserDetails赋给认证通过的Authentication的principal,然后再将该Authentication保存在SecurityContext中。在应用中,如果需要使用用户信息,可以通过SecurityContextHolder获取存放在SecurityContext中的Authentication的principal,即UserDetails实例。
    5.GrantedAuthority
    
        Authentication的getAuthorities()方法可以返回当前Authentication对象拥有的权限(一个GrantedAuthority类型的数组),即当前用户拥有的权限。GrantedAuthority是一个接口,通常是通过UserDetailsService进行加载,然后赋给UserDetails。
    6.DaoAuthenticationProvider
    
        在Spring Security安全框架中,默认使用DaoAuthenticationProvider实现AuthenticationProvider接口进行用户认证的处理。DaoAuthenticationProvider进行认证时,需要一个UserDetailsService来获取用户信息UserDetails。当然我们可以实现自己的AuthenticationProvider,进而改变认证方式。
    7.PasswordEncoder
    
        在Spring Security安全框架中,是通过PasswordEncoder接口完成对密码的加密。Spring Security对PasswordEncoder有多种实现,包括MD5加密、SHA-256加密等,开发者只需直接使用即可。在Spring Boot应用中,使用BCryptPasswordEncoder加密是较好的选择。BCryptPasswordEncoder使用BCrypt的强散列哈希加密实现,并可以由客户端指定加密强度,强度越高安全性越高。
    Spring Security的验证机制
    
        Spring Security的验证机制是由许多Filter实现的,Filter将在Spring MVC前拦截请求,主要包括注销Filter(LogoutFilter)、用户名密码验证Filter(UsernamePasswordAuthenticationFilter)等内容。Filter再交由其他组件完成细分的功能,最常用的UsernamePasswordAuthenticationFilter会持有一个AuthenticationManager引用,AuthenticationManager是一个验证管理器,专门负责验证。AuthenticationManager持有一个AuthenticationProvider集合,AuthenticationProvider是做验证工作的组件,验证成功或失败之后调用对应的Hanlder(处理)。
    Spring Boot的支持
    
        在Spring Boot应用中,我们只需引入spring-boot-starter-security依赖即可使用Spring Security安全框架,这是因为Spring Boot对Spring Security提供了自动配置功能。从org.springframework.boot.autoconfigure.security.SecurityProperties类中,我们可以看到使用以“spring.security”为前缀的属性配置了Spring Security的相关默认配置。因此,我们在实际应用开发中只需自定义一个类继承WebSecurityConfigurerAdapter,无须使用@EnableWebSecurity注解,即可自己扩展Spring Security的相关配置。
  • 相关阅读:
    从马琳决赛被翻盘想到的
    C语言中的位运算
    瑞星杀毒软件所有监控已禁用!
    回来了,重新开始
    使用 javascript 标记高亮关键词
    我的webgis客户端引擎AIMap
    RPM 命令大全
    终结IE6下背景图片闪烁问题
    linux下挂载硬盘光驱和U盘
    在JavaScript中实现命名空间
  • 原文地址:https://www.cnblogs.com/tszr/p/15375522.html
Copyright © 2011-2022 走看看