源码时代Java干货分享|SpringSecurity快速上手秘籍

Posted IT-source

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码时代Java干货分享|SpringSecurity快速上手秘籍相关的知识,希望对你有一定的参考价值。

前言

至今Java能够如此的火爆Spring做出了很大的贡献,它的出现让Java程序的编写更为简单灵活,而Spring如今也形成了自己的生态圈,今天咱们探讨的是Spring旗下的一个款认证工具:SpringSecurity,如今认证框架主流“shiro”和“SpringSecurity”,由于和Spring的无缝衔接,使用SpringSecurity的企业也越来越多。

基本概念

1.什么是认证认证是对主体/用户身份的确认,在我们的生活中随处可见认证场景,如:小区门禁卡,人脸识别,指纹识别等都是对用户身份的确认,在传统的应用中我们通常使用用户名/用户ID和密码来进行用户的身份确认,即登录,但登录的方式不仅限制于用户名/密码的方式,认证是我们应用的第一道安全门,所以对于整个系统的安全来说显得极其重要。

2.什么是授权控制不同的用户访问不同的权限 ,用户认证成功后,就可以对某些资源进行访问,但是不同的用户有不同的资源访问权利,那么对用户的授权也都不一样。如:公司老板拥有对公司的所有权限,而部门主管只能有对自己管理的部门的权限,所以在程序中授权的过程就是赋予不同用户不同权限的过程。

3.RBAC介绍RBAC:是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。 举例:可以把部门的展示,添加,修改,删除等资源或功能打包成角色“部门管理”,然后把“部门管理”这个角色赋予某个用户,那么这个用户就是部门管理员,拥有部门的相关权限。RBAC 认为授权实际上是Who 、What 、How 三元组之间的关系,也就是Who 对What 进行How 的操作。

  • 主体(Who ) :是权限的拥有者或主体(如:User,Role)
  • 资源 (what):是操作或对象,如:页面,菜单,按钮,控制器(controller,hanler)等
  • 权限(how) :具体的权限, 如:张三可以删除员工。
    那么删除员工就是一个权限

4.SpringSecurity介绍

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,SrpingSecurity为我们在做认证,授权方面提供了很多方便。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

本案例是基于SpringBoot集成SpringSecurity,如果对SpringBoot不熟悉的小伙伴请先学习SpringBoot

1.搭建工程
基于SpringBoot搭建工程

2.导入依赖

<parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.0.5.RELEASE</version>
   </parent>
 ​
   <groupId>cn.itsource.security</groupId>
   <artifactId>security-demo</artifactId>
   <version>1.0-SNAPSHOT</version>
 ​
   <name>security-demo</name>
 ​
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <maven.compiler.source>1.8</maven.compiler.source>
     <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
 ​
   <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>
     
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
     </dependency>
 ​
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.12</version>
       <scope>test</scope>
     </dependency>
   </dependencies>

SpringBoot集成Security基础依赖:spring-boot-starter-security

3.主配置类

@SpringBootApplication
 public class ApplicationConfig 
     public static void main(String[] args) 
         SpringApplication.run(ApplicationConfig.class);
     
 

4.控制器

这里编写了一个登陆成功后的跳转地址

@Controller
 public class AuthController 
     //登录成功后重定向地址
     @RequestMapping("/loginSuccess")
     @ResponseBody
     public String loginSuccess()
         return "登录成功";
     
 

5.UserDetailService

  • UserDetailsService是SpringSecurity提供用来获取认证用户信息(用户名,密码,用户的权限列表)的接口,我们可以实现该接口,复写loadUserByUsername(username)方法加载我们数据库中的用户信息

  • UserDetails是SpringSecurity用来封装用户信息的对象,我们使用它的实现类User封装用户信息并返回,我们这里模拟从数据库查询用户名

/**
  * 用来提供给security的用户信息的service,
  * 我们需要复写 loadUserByUsername 方法返回数据库中的用户信息
  */
 @Service
 public class UserDetailServiceImpl implements UserDetailsService 
 ​
     /**
      * 加载数据库中的认证的用户的信息:用户名,密码,用户的权限列表
      * @param username: 该方法把username传入进来,我们通过username查询用户的信息
      (密码,权限列表等)然后封装成 UserDetails进行返回 ,交给security 。
      */
     @Override
     public UserDetails loadUserByUsername(String username)
     throws UsernameNotFoundException 
         //User是security内部的对象,UserDetails的实现类 ,
         用来封装用户的基本信息(用户名,密码,权限列表)
 ​
         //模拟存储在数据库的用户的密码:123
         String password = "123";
 ​
         //用户的权限列表,暂时为空
         Collection<GrantedAuthority> authorities = new ArrayList<>();
 ​
         User user = new User(username,password, authorities);
 ​
         return user;
     
 

6.配置Security
SpringSecurity提供了一个配置类WebSecurityConfigurerAdapter用来提供给我们对SpringSecurity做自定义配置,我们需要配置如下几个信息:
认证管理配置需要指定我们自己定义的userDetailService,这样SpringSecurity才会调用我们的userDetailService从而获取到用户信息,同时指定密码比对方式

授权规则配置配置请求拦截规则,哪些资源需要认证,哪些资源不需要认证等等

@Configuration
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
 ​
     @Autowired
     private UserDetailServiceImpl userDetailService ;
 ​
     //把我们自己的userDetailService替换掉默认的userDetailService,然后指定密码编码方式和密码匹配
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception 
         auth.userDetailsService(userDetailService).passwordEncoder(new PasswordEncoder() 
             @Override
             public String encode(CharSequence rawPassword) 
                 //对密码进行加密后返回,可以自定义加密方式(如md5),因为我们使用的明文所以直接返回
                 return rawPassword.toString();
             
             @Override
             public boolean matches(CharSequence rawPassword, String encodedPassword) 
                 //密码比较方式
                 return rawPassword.equals(encodedPassword);
             
         );
     
 ​
     //授权规则配置
     @Override
     protected void configure(HttpSecurity http) throws Exception 
         http.authorizeRequests()
                 .antMatchers("/login").permitAll()  //登录路径放行
                 .anyRequest().authenticated() //其他路径都要拦截
                 .and().formLogin()  //允许表单登录, 设置登陆页
                 .successForwardUrl("/loginSuccess") // 设置登陆成功页
                 .and().logout().permitAll();    //登出
     
 ​
 

7.访问测试
启动访问: http://localhost:8080/login 输入用户名:zs ,密码 :123 (见UserDetailServiceImpl.loadUserByUsername ) ,登录成功页面跳转/loginSuccess,显示“登录成功”

总结

SpringBoot+SpringSecurity集成入门案例到这里就结束了,这里并没有多SpringSecurity原理做过多解释(留在后面章节),那么这个案例大概的实现思路是:

1.SpringSecurity根据我们在WebSecurityConfig中的配置会对除了“/login”之外的资源进行拦截做认证检查

2.如果没有认证会跳转到默认的认证页面“/login” ,

3.输入用户名和密码后点击登录,SpringSecurity会带着用户名调用 UserDetailsService.loadUserByUsername获取用户的认证信息(用户名,密码,权限等),

4.然后执行认证工作:表单密码和loadUserByUsername加载的数据库的密码进行匹配(PasswordEncoder)5.认证成功跳转成功地址

以上是关于源码时代Java干货分享|SpringSecurity快速上手秘籍的主要内容,如果未能解决你的问题,请参考以下文章

源码时代Java干货分享|SpringSecurity快速上手秘籍

源码时代Java干货分享|带你了解原型模式_prototype

源码时代Java干货分享|带你认识Zookeeper 分布式服务框架

源码时代Java干货分享|手把手教你用maven构建docker镜像

源码时代Java干货分享|手把手教你SpringBoot配置ssl证书

源码时代Java干货分享|Shell脚本编程学习入门,只需两个步骤,包你学会!