Spring Security如何使用数据库登录认证授权(security,spring,数据库,开发技术)

时间:2024-05-04 16:29:53 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

一、搭建项目环境

1、创建 RBAC五张表

RBAC,即基于角色的权限访问控制(Role-Based Access Control),就是用户通过角色与权限进行关联。
在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。

在 MySQL数据库中,创建如下几个表:

DROPTABLEIFEXISTSsys_user;CREATETABLEsys_user(idBIGINTNOTNULLAUTO_INCREMENTCOMMENT'主键id',usernameVARCHAR(60)COMMENT'用户名',passwordVARCHAR(255)COMMENT'密码',statustinyint(1)COMMENT'用户状态,1-开启-0禁用',password_non_expiredtinyint(1)COMMENT'密码是否失效,1-可用,0-失效',PRIMARYKEY(id))COMMENT='用户表';DROPTABLEIFEXISTSsys_role;CREATETABLEsys_role(idBIGINTNOTNULLAUTO_INCREMENTCOMMENT'主键id',role_nameVARCHAR(64)NOTNULLCOMMENT'角色名',role_descVARCHAR(64)NOTNULLCOMMENT'角色描述',PRIMARYKEY(id))COMMENT='角色表';DROPTABLEIFEXISTSsys_permission;CREATETABLEsys_permission(idBIGINTNOTNULLAUTO_INCREMENTCOMMENT'主键id',parent_idBIGINTCOMMENT'父id',permission_nameVARCHAR(64)COMMENT'菜单名称',permission_urlVARCHAR(255)COMMENT'菜单地址',PRIMARYKEY(id))COMMENT='权限表';DROPTABLEIFEXISTSsys_user_role;CREATETABLEsys_user_role(idBIGINTNOTNULLAUTO_INCREMENTCOMMENT'主键id',user_idBIGINTNOTNULLCOMMENT'用户id',role_idBIGINTCOMMENT'角色id',enabledtinyint(1)DEFAULT1COMMENT'是否有效',PRIMARYKEY(id))COMMENT='用户角色关联表';DROPTABLEIFEXISTSsys_role_permission;CREATETABLEsys_role_permission(idBIGINTNOTNULLAUTO_INCREMENTCOMMENT'主键id',role_idBIGINTNOTNULLCOMMENT'角色id',permission_idBIGINTCOMMENT'权限id',PRIMARYKEY(id))COMMENT='角色权限表';

Spring Security如何使用数据库登录认证授权

2、创建项目

创建 Mavne 项目,Springboot + Spring Security + MyBatis + MySQL + jsp。

1)配置文件如下

server:port:9090#jsp配置spring:mvc:view:prefix:/pages/suffix:.jspdatasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://localhost:3306/security_authority?useUnicode=true;characterEncoding=utf8;useSSL=true;serverTimezone=GMTusername:rootpassword:123456#mybatis配置mybatis:configuration:map-underscore-to-camel-case:truemapper-locations:classpath:mybatis/mapper/*.xmllogging:level:com.charge.learn.springsecurity.springboot.security.jsp.dao:debug

2)启动类

@SpringBootApplication@MapperScan("com.charge.learn.springsecurity.springboot.security.jsp.dao")publicclassSpringSecurityApplication{publicstaticvoidmain(String[]args){SpringApplication.run(SpringSecurityApplication.class,args);}}

Spring Security如何使用数据库登录认证授权

二、整合 Spring Security实现用户认证

1、后端整合

1.1 用户

Spring Security的用户对象是 UserDetail类型,Spring Security在认证流程中只认 UserDetail用户。

  • 通过 UserDetailsService的 loadUserByUsername方法获取 UserDetail用户。

  • 认证成功之后,调用的是这个带有三个参数的 UsernamePasswordAuthenticationToken构造方法,将 角色信息添加到了ArrayList<GrantedAuthority>集合中。

  • 在 successfulAuthentication 方法中,将认证信息存储到了SecurityContext中。

Spring Security如何使用数据库登录认证授权

UserDetail接口的方法(根据用户业务来处理这几个值)。

  • boolean enabled 账户是否可用

  • boolean accountNonExpired 账户是否失效

  • boolean credentialsNonExpired 账户密码是否失效

  • boolean accountNonLocked 账户是否锁定

  • Collection<? extends GrantedAuthority> getAuthorities() 获取账户的所有权限(用户角色)

注意:四个布尔类型的参数都为 true时,然后成功,否则,有一个为 false,就会认证失败。

所以,我们可以将我们的用户封装成 UserDetail对象。
这里我们让用户对象实现 UserDetail接口,那么我们用户就属于 UserDetail类型的用户,然后实现接口的方法。

publicclassSysUserimplementsUserDetails{privateLongid;privateStringusername;privateStringpassword;privateBooleanstatus;//用户状态,1-开启-0禁用privateBooleanpasswordNonExpired;//密码是否失效,1-可用,0-失效/***用户关联的所有角色*/privateList<SysRole>roles=newArrayList<>();//get、set方法//标记该字段不做json处理@JsonIgnore@OverridepublicCollection<?extendsGrantedAuthority>getAuthorities(){returnroles;}@JsonIgnore@OverridepublicbooleanisAccountNonExpired(){returntrue;}@JsonIgnore@OverridepublicbooleanisAccountNonLocked(){returntrue;}@JsonIgnore@OverridepublicbooleanisCredentialsNonExpired(){returnpasswordNonExpired==null?false:passwordNonExpired;}@JsonIgnore@OverridepublicbooleanisEnabled(){returnstatus==null?false:status;}}

1.2 角色

Spring Security的权限对象是 GrantedAuthority类型。通过它的值来实现权限管理的。

Spring Security如何使用数据库登录认证授权

所以,我们让角色对象实现GrantedAuthority接口,那么我们角色就属于 GrantedAuthority类型,然后实现接口的方法。
上面用户可以直接将 角色添加到 Collection<? extends GrantedAuthority>集合中。

publicclassSysRoleimplementsGrantedAuthority{privateLongid;privateStringroleName;privateStringroleDesc;//get、set方法//标记该字段不做json处理@JsonIgnore@OverridepublicStringgetAuthority(){returnroleName;}}

1.3 SysUserService接受继承UserDetailsService类

Spring Security在认证流程中通过 UserDetailsService的 loadUserByUsername方法获取 UserDetail用户。

Spring Security如何使用数据库登录认证授权

所以,我们让 UserService接口继承 UserDetailsService类,然后重写 loadUserByUsername方法。

在 loadUserByUsername方法中,获取我们的用户信息( UserDetail类型),记得将用户关联的角色也赋值为用户信息。

publicinterfaceSysUserServiceextendsUserDetailsService{voidsave(SysUseruser);}
@Service@TransactionalpublicclassSysUserServiceImplimplementsSysUserService{ @Autowired privateSysUserMappersysUserMapper; @Autowired privateSysRoleMappersysRoleMapper; @Autowired privateBCryptPasswordEncoderpasswordEncoder; @Override publicvoidsave(SysUsersysUser){ //将密码加密入库 sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword())); sysUserMapper.insert(sysUser); } /** *认证业务 * *@paramusername *-用户在浏览器输入的用户名 *@returnUserDetails-SpringSecurity的用户对象,返回null表示认证失败! *@throwsUsernameNotFoundException */ @Override publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{ /** *用户信息和角色信息可以一步关联查询到位得到SysUser,我这里分开查询 */ //1.查询用户 SysUsersysUser=sysUserMapper.getByUsername(username); if(sysUser==null){ returnnull; } //2.获取用户关联的所有角色 List<SysRole>sysRoles=sysRoleMapper.listAllByUserId(sysUser.getId()); sysUser.setRoles(sysRoles); System.out.println("====>sysUser="+sysUser.toString()); returnsysUser; }}

mapper.xml中的几个方法

<selectid="getByUsername"resultMap="BaseResultMap">selectid,username,password,status,password_non_expiredfromsys_userwhereusername=#{username}</select><selectid="listAllByUserId"resultMap="BaseResultMap">SELECTr.id,r.role_namerole_name,r.role_descrole_descFROMsys_roler,sys_user_roleurWHEREr.id=ur.role_idANDur.user_id=#{userId}</select>

1.4 创建 SpringSecurity配置类

自定义一个配置类,添加@EnableWebSecurity注解,并继承WebSecurityConfigurerAdapter类。然后就拥有了 SpringSecutiry的所有默认配置。我们也可以修改配置。

@Configuration@EnableWebSecuritypublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredprivateSysUserServiceuserService;//加密对象注入IOC容器@BeanpublicBCryptPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}//1.指定认证对象的来源(内存或者数据库),指定加密方式@Overridepublicvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.userDetailsService(userService).passwordEncoder(passwordEncoder());}//2.SpringSecurity配置相关信息@Overridepublicvoidconfigure(HttpSecurityhttp)throwsException{//释放静态资源,指定拦截规则,指定自定义的认证和退出页面,csrf配置等http.authorizeRequests()//指定拦截规则.antMatchers("/login.jsp","failer.jsp","/css/**","/img/**","/plugins/**").permitAll()//释放这些资源,不拦截.antMatchers("/**").hasAnyRole("USER","ADMIN")//所有资源都需要这些角色中的一个.anyRequest().authenticated()//其他请求,必须认证通过之后才能访问.and()//表示新的一个配置开始//指定自定义的认证页面.formLogin().loginPage("/login.jsp").loginProcessingUrl("/login").successForwardUrl("/index.jsp").failureForwardUrl("/failer.jsp").permitAll()//释放这些资源,不拦截登录.and()//指定自定义的退出页面.logout().logoutSuccessUrl("/logout").invalidateHttpSession(true)//清楚session.logoutSuccessUrl("/login.jsp").permitAll()//.and()//禁用csrf配置,默认开启的(一般不写,页面要加csrf),这里我们测试下//.and()//.csrf()//.disable();}

主要配置信息如下:

  • 指定认证对象 SysUserService (UserDetailsService类型)

  • 指定了用户密码使用的加密对象

  • SpringSecurity配置相关信息,比如:指定拦截规则,指定自定义的认证页面,csrf等。

2、前端整合

在 Spring Security 中,如果我们不做任何配置,默认的登录页面和登录接口的地址都是 /login,即默认会存在如下两个请求:

  • GET http://localhost:8080/login

  • POST http://localhost:8080/login

如果是 GET 请求表示你想访问登录页面,如果是 POST 请求,表示你想提交登录数据。默认的表单字段为 username和password。

SpringSecurity 默认 是开启 csrf防护机制。
所以,在自定义的表单上添加上 _csrf隐藏input(必须要写在form表单里面)。

引入security标签库<%@tagliburi="http://www.springframework.org/security/tags"prefix="security"%><security:csrfInput/>

启动项目,登录认证访问ok.

三、整合 Spring Security实现用户授权

认证过程获取用户信息时,我们已经把用户关联的角色信息设置到了 UserDetails中,所以,我们只需要分配 资源访问的角色就可以了。

1、后端

1.1 开启 Spring Security权限控制

Spring Security可以通过注解的方式来控制类或者方法的访问权限。支持开启权限控制的注解类型如下:

  • jsr250-annotations:表示支持 jsr250-api的注解

  • pre-post-annotations:表示支持 spring表达式注解

  • secured-annotations:这才是 Spring Security提供的注解

Spring Security如何使用数据库登录认证授权

在实际开发中,用一类即可,三个都开启也没关系。
在 SpringSecurity配置类上 添加 @EnableGlobalMethodSecurity注解,表示开启 Spring Security权限控制,这里我们三类都开启了。

@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true,jsr250Enabled=true)publicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{...
@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true,jsr250Enabled=true)publicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{...

1.2 在角色对应类或者方法上添加权限注解

1.2.1 使用 Spring Security注解

  • @Secured({“ROLE_ADMIN”,“ROLE_PRODUCT”})

@Controller@RequestMapping("/user")@Secured("ROLE_ADMIN") //表示当前类中所有方法需要ROLE_ADMIN才能访问publicclassUserController{@AutowiredprivateUserServiceuserService;@RequestMapping("/findAll")publicStringfindAll(Modelmodel){List<SysUser>list=userService.findAll();model.addAttribute("list",list);return"user-list";}。。。}

1.2.2 使用 Spring表达式注解

  • @PreAuthorize(“hasAnyRole(&lsquo;ROLE_ADMIN&rsquo;,&lsquo;ROLE_PRODUCT&rsquo;)”)

@Controller@RequestMapping("/product")publicclassProductController{@RequestMapping("/findAll")//表示当前类中findAll方法需要ROLE_ADMIN或者ROLE_PRODUCT才能访问@PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_PRODUCT')")publicStringfindAll(){return"product-list";}}

1.2.3 使用 JSR-250注解

  • @RolesAllowed({“ROLE_ADMIN”,“ROLE_User”})

@Controller@RequestMapping("/order")@RolesAllowed({"ROLE_ADMIN","ROLE_USER"})//表示当前类中所有方法都需要ROLE_ADMIN或者ROLE_User才能访问publicclassOrderController{@RequestMapping("/findAll")publicStringfindAll(){return"order-list";}}

2、前端

在jsp业页面中,对每个菜单资源通过 SpringSecurity标签库指定访问所需的角色。

<%@tagliburi="http://www.springframework.org/security/tags"prefix="security"%><!--指定访问所需角色--><security:authorizeaccess="hasAnyRole('ROLE_ADMIN','等等')">

启动项目,通过不同的用户登录,授权访问ok.

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Spring Security如何使用数据库登录认证授权的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Python+OpenCV如何实现基于颜色的目标识别下一篇:

11 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18