ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringSecurity:helloworld

2022-05-21 00:01:53  阅读:215  来源: 互联网

标签:web Spring springframework SpringSecurity helloworld org security Security


5.20

Spring Security

Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的成员。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。

正如你可能知道的关于安全方面的两个主要区域是“认证”和“授权”(或者访问控制),一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分,这两点也是 Spring Security 重要核心功能。

  • 用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。通俗点说就是系统认为用户是否能登录。
  • 用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。通俗点讲就是系统判断用户是否有权限去做某些事情。

特点

SpringSecurity 特点:

  • 和 Spring 无缝整合。

  • 全面的权限控制。

  • 专门为Web 开发而设计。

    • 旧版本不能脱离Web 环境使用。

    • 新版本对整个框架进行了分层抽取,分成了核心模块和Web 模块。单独引入核心模块就可以脱离Web 环境。

  • 重量级。


Shiro

Apache 旗下的轻量级权限控制框架。

特点:

  • 轻量级。Shiro 主张的理念是把复杂的事情变简单。针对对性能有更高要求的互联网应用有更好表现。
  • 通用性。
    • 好处:不局限于Web 环境,可以脱离Web 环境使用。
    • 缺陷:在Web 环境下一些特定的需求需要手动编写代码定制。

比较

相对于 Shiro,在 SSM 中整合 Spring Security 都是比较麻烦的操作,所以,Spring Security 虽然功能比 Shiro 强大,但是使用反而没有 Shiro 多(Shiro 虽然功能没有Spring Security 多,但是对于大部分项目而言,Shiro 也够用了)。自从有了 Spring Boot 之后,Spring Boot 对于 Spring Security 提供了自动化配置方案,可以使用更少的配置来使用 Spring Security。

  • SSM + Shiro
  • Spring Boot/Spring Cloud + Spring Security

入门案例

  • 引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
  • 编写controller

    @RestController
    @RequestMapping("test")
    public class TestController {
    
        @GetMapping("add")
        public String add(){
            return "hello security";
        }
    }
    
  • 直接访问

image

  • 用户名和密码

    SpringSecurity默认用户名user,而密码会打印在控制台。

    Using generated security password: 4bb96c68-fe1f-4cc4-970f-7d4a0931dfd8
    

SpringSevurity本质上是一个过滤器链

org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFil ter
org.springframework.security.web.context.SecurityContextPersistenceFilter org.springframework.security.web.header.HeaderWriterFilter org.springframework.security.web.csrf.CsrfFilter org.springframework.security.web.authentication.logout.LogoutFilter org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter org.springframework.security.web.savedrequest.RequestCacheAwareFilter org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter org.springframework.security.web.authentication.AnonymousAuthenticationFilter org.springframework.security.web.session.SessionManagementFilter org.springframework.security.web.access.ExceptionTranslationFilter org.springframework.security.web.access.intercept.FilterSecurityInterceptor

每一个过滤器都放行才能正常访问!

几个重要的过滤器

FilterSecurityInterceptor

本质上过滤器是拦截器的

是一个方法级的权限过滤器, 基本位于过滤链的最底部

  • 该拦截器实现了Filter接口。
  • 主要所用是判断其他过滤器是否放行?

ExceptionTranslationFilter

是个异常过滤器,用来处理在认证授权过程中抛出的异常

UsernamePasswordAuthenticationFilter

对/login 的 POST 请求做拦截,校验表单中用户名,密码。


过滤器加载过程

  • 需要配置一个过滤器(DelegatingFilterProxy

  • 通过WebApplicationContext中获取FilterChainProxy的过滤器。

  • FilterChainProxy中,通过doFilterInternal()方法获取List,然后使用doFilter()方法继续后续步骤。

image


两个重要接口(两个重要极限,既视感。。)

  • UserDetailsService
  • PasswordEncoder

UserDetailsService

当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。

查询用户名和密码的过程

  • 创建类并继承UsernamePasswordAuthenticationFilter并重写三个方法
  • 创建类实现UserDetailService编写查询过程,返回User对象。该User对象由框架提供

PasswordEncoder

用于对明文密码的加密!

一般用于返回User对象密码的加密

BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器,平时多使用这个解析器。
BCryptPasswordEncoder 是对bcrypt 强散列方法的具体实现。是基于 Hash 算法实现的单向加密。可以通过 strength 控制加密强度,默认 10.


设置登录的用户名密码

  1. 通过配置文件
  2. 通过配置类
  3. 自定义实现类

通过配置文件

spring:
  security:
    user:
      name: hello
      password: hello

通过配置类

@Configuration
public class UserConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //对密码进行加密
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        auth.inMemoryAuthentication().withUser("boerk").password(encode).roles("admin");
    }
	//需要向Spring容器中注入PasswordEncoder对象,否则会报错
    //这里通过一个BeanConfig实现
}

如果明文输入密码,则使用{noop}123456

auth.inMemoryAuthentication().withUser("boerk").password("{noop}123456").roles("admin");

通过自定义实现类

@Service
public class UserDetailsServiceImpl  implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode("123456");
        UserDetails build = User.withUsername("zhangsan").password(encode).authorities("admin").build();
        return build;
    }
}

或者!

//实现类
@Service
public class UserDetailsServiceImpl  implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        List<GrantedAuthority> auths = AuthorityUtils.createAuthorityList("role");
        return new User("boerk",new BCryptPasswordEncoder().encode("123456"),auths);
    }
}
//config
@Configuration
public class UserConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }
}

如果使用PasswordEncoder的实现类对象,则必须向容器注入PasswordEncoder

@Configuration
public class BeanConfig {
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

总结:用户认证的方式

  1. 通过配置文件实现
  2. 通过配置类,继承WebSecurityConfigureAdapter接口,重写configure方法,通过该方法入参对象设置。
  3. 通过自定义实现类的方式,实现UserDetailsService,重写loadUserByUserName,通过User对象设置。

标签:web,Spring,springframework,SpringSecurity,helloworld,org,security,Security
来源: https://www.cnblogs.com/Boerk/p/16294078.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有