- 设计数据库
数据库权限概念
角色用户组权限关联
数据库实体图:
2、将用户权限表与springsecurity相关联
使用自定义的provider
<security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="multipleAuthenticationProvider"> <!-- <security:user-service> <security:user name="admin" password="admin" authorities="ROLE_USER"/> <security:user name="manager" password="manager" authorities="ROLE_USER"/> </security:user-service> --> <!-- 内存用户测试 --> <!-- <security:jdbc-user-service data-source-ref=""/> --> <!-- 数据库源测试 --> <!-- <security:ldap-user-service/> --> <!-- ladp数据源测试 --> <!-- <security:password-encoder> --> <!-- 密码encoder --> <!-- </security:password-encoder> --> </security:authentication-provider> </security:authentication-manager>
<!-- 配置身份验证器 定义登陆验证过滤器 过后调用 --> <bean id="multipleAuthenticationProvider" class="com.bbs.security.authentication.provider.MultipleAuthenticationProvider"> <property name="authenticationProviders"> <list> <ref bean="forendAuthenticationProvider" /> </list> </property> </bean>
<!-- 前台验证器并构建新用户凭证 定义登陆验证过滤器 过后调用 并调用userDetailsService 通过用户名将用户和用户的角色装配 数据库中验证用户 重新构建UsernamePasswordAuthenticationToken传递给决策管理器进行授权管理 --> <bean id="forendAuthenticationProvider" class="com.bbs.security.authentication.provider.ForendAuthenticationProvider"> <property name="userDetailsService" ref="forendUserDetailsService"></property> <property name="passwordEncoder" ref="shaPasswordEncoder"></property> <property name="saltSource" ref="saltSource"></property> </bean>
<!-- 配置加密策略 --> <bean id="shaPasswordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"> <!-- 加密方式 SHA-256 --> <constructor-arg value="256" /> </bean>
<!-- 配置密码的盐值 --> <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource"> <!-- 以用户名作为加密盐值 --> <property name="userPropertyToUse" value="username"></property> </bean>
<bean id="forendUserDetailsService" class="com.bbs.security.authentication.userdetailservice.ForendUserDetailsService"></bean>
运行顺序是解释xml,提供权限验证,manager提供管理权限验证,加载bean,配置bean。
自定义的multipleAuthenticationProvider
import java.util.List; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; public class MultipleAuthenticationProvider implements AuthenticationProvider { private List<AuthenticationProvider> authenticationProviders; /** * 根据登录前的用户凭证筛选匹配的Provider,并构建新的用户凭证供登陆后的决策器调用 身份验证器 */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { Authentication authenticationToken = null; for (AuthenticationProvider authenticationProvider : authenticationProviders) { if (authenticationProvider.supports(authentication.getClass())) { authenticationToken = authenticationProvider .authenticate(authentication); } } return authenticationToken; } public boolean supports(Class<? extends Object> authentication) { return true; } public List<AuthenticationProvider> getAuthenticationProviders() { return authenticationProviders; } public void setAuthenticationProviders( List<AuthenticationProvider> authenticationProviders) { this.authenticationProviders = authenticationProviders; } }
这里才是真正的provider,前面那个只是提供赛选
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import com.bbs.security.authentication.token.ForendAuthenticationToken; /** * 数据库中验证用户 * @author Administrator * */ public class ForendAuthenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider { @Override /** * 数据库中验证用户 重新构建UsernamePasswordAuthenticationToken传递给决策管理器进行授权管理 */ public Authentication authenticate(Authentication authentication) throws AuthenticationException { ForendAuthenticationToken authenticationToken = (ForendAuthenticationToken) authentication; //获取验证实体 userDetails UserDetails userDetails = getUserDetailsService().loadUserByUsername( authenticationToken.getPrincipal().toString()); // 获得的用户输入密码 String presentedPassword = authentication.getCredentials().toString(); // 获得用户名,作为加密盐值 加盐值与配置文件中的盐值属性相匹配 Object salt = getSaltSource().getSalt(userDetails); // 判断密码是否匹配 if (!getPasswordEncoder().isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { throw new BadCredentialsException("password is error"); } // 重新构建UsernamePasswordAuthenticationToken传递给决策管理器进行授权管理 return new UsernamePasswordAuthenticationToken(userDetails, authentication.getPrincipal(), userDetails.getAuthorities()); } /** * 前台用户凭证 是否正确 * @param authentication * @return */ @Override public boolean supports(Class<?> authentication) { return ForendAuthenticationToken.class.isAssignableFrom(authentication); } }
那它是如何从界面得到用户输入的账号与密码并且与数据库中得到的密码进行匹配,这里要进行自己定义的loginFilter进行过滤拦截
<!-- 替换默认的登陆验证Filter --> <security:custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER" />
自己定义的loginfilter,必须继承UsernamePasswordAuthenticationFilter
<bean id="loginFilter" class="com.bbs.security.authentication.filter.MultipleUsernamePasswordAuthenticationFilter"> <!-- 登陆页面URL --> <property name="filterProcessesUrl" value="/login_check" /> <!-- 注入不同类型的用户凭证 --> <property name="tokenResolvers"> <list> <ref bean="forendAuthenticationTokenResolver" /> </list> </property> <!-- 校验用户名及密码,并对用户授权 --> <property name="authenticationManager" ref="authenticationManager" /> <!-- 验证通过所执行的请求 --> <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" /> <!-- 验证未通过所执行的请求 --> <property name="authenticationFailureHandler" ref="authenticationFailureHandler" /> <!-- 自动登录 --> <property name="rememberMeServices" ref="rememberMeServices"></property> </bean>
import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; //import com.ssh.util.CaptchaUtil; //import com.ssh.util.ExeceptionUtil; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; //import com.ssh.util.CaptchaUtil; /** * 登陆验证处理类 form表单验证 并传出用户凭证 * 继承UsernamePasswordAuthenticationFilter * @author Administrator * */ public class MultipleUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private List<AuthenticationTokenResolver> tokenResolvers;//用户配置的用户凭证标记类(用户类型)以此为依据装配具体的用户凭证 策略模式 public static final String CAPTCHA = "captcha"; // 验证码 /** * 重写身份验证方法 */ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { // 校验验证码 checkValidateCode(request); for (AuthenticationTokenResolver tokenResolver : tokenResolvers) { // 检验登陆类型 if (tokenResolver.support(request)) { // 获得具体的用户凭证 Authentication authentication = tokenResolver.resolve(request); HttpSession session = request.getSession(false); if (session != null || getAllowSessionCreation()) { request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, authentication.getPrincipal().toString()); } // 验证用户凭证 return this.getAuthenticationManager().authenticate( authentication); } } // throw new UnsupportedOperationException( // ExeceptionUtil.getValue("MultipleUsernamePasswordAuthenticationFilter_attemptAuthentication"));//"No authentication token resolver found!" return null; } /** * 使用工具类校验输入的验证码是否匹配 * * @param request */ protected void checkValidateCode(HttpServletRequest request) { // if (!CaptchaUtil.validateCaptchaByRequest(request)) { // throw new AuthenticationServiceException("ValidateCode Not Equals"); // } } public List<AuthenticationTokenResolver> getTokenResolvers() { return tokenResolvers; } public void setTokenResolvers( List<AuthenticationTokenResolver> tokenResolvers) { this.tokenResolvers = tokenResolvers; } }
这里可以自定义全部拦截实现,可以得到用户输入的密码,后台自己实现把账号传给UsernamePasswordAuthenticationToken,接下来就是ForendUserDetailsService得到账号,实现代码为
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import javax.annotation.Resource; import org.springframework.dao.DataAccessException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.transaction.annotation.Transactional; /** * 通过用户名将用户和用户的角色装配 * @author Administrator * */ public class ForendUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { // TODO Auto-generated method stub UserDetail userdetail=new UserDetail(); return userdetail; }
}
UserDetail必须实现UserDetails接口
import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; public class UserDetail implements UserDetails{ private String password; private String username; private Collection<GrantedAuthority> grantedauthoritys; private boolean isEnabled; //账户是否有效 @Override public Collection<GrantedAuthority> getAuthorities() { // TODO Auto-generated method stub return grantedauthoritys; } @Override public String getPassword() { // TODO Auto-generated method stub return "a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1"; } @Override public String getUsername() { // TODO Auto-generated method stub return "admin"; } @Override public boolean isAccountNonExpired() { // TODO Auto-generated method stub return false; } @Override public boolean isAccountNonLocked() { // TODO Auto-generated method stub return false; } @Override public boolean isCredentialsNonExpired() { // TODO Auto-generated method stub return false; } @Override public boolean isEnabled() { // TODO Auto-generated method stub return true; } }
这里面可以自己从数据库中进行得到密码,赋予权限,并且自定义权限字符串,然后每次登陆时就会把权限与配置文件中进行比较
暂时发现的缺点是不能进行动态的配置权限,但是可以自己进行补充,扩展,这点等分析详细后在补充,思路是找到权限验证的类,把用户输入的URL权限与当前用户的浏览申请的URL进行比对,为了考虑运行速度的问题,还必须要把所有的浏览权限保存在内存中,否则每次都会从数据库中进行查询,减低了效率
大家都想自定义实现权限验证,这种方法告诉大家了
好了,如果有问题,请留言,由于分析难度比较大,只能慢慢来了
相关推荐
后端使用SpringBoot框架进行业务逻辑开发,利用Spring Security实现权限控制。数据库采用MySQL进行数据存储,使用MyBatis进行数据访问。 权限控制模块设计包括用户、角色和权限三个主要模块。用户模块用于管理用户...
详细介绍请看博客:https://blog.csdn.net/hyh17808770899/article/details/109733851 源码完全可行,于2022.03.14根据该博客创建,本资源内容包含项目源码、所关联的数据库表,以及postman测试接口JSON文档
Spring security 认证-ch03是关联数据库,查询权限,ch01和ch02都是写死在配置文件中,ch03是直接从数据库中读取。下一个例子为Spring security 认证-ch04,请多关注。
控制层:Spring MVC、FastJSON、RestTemplate、Spring Security Oauth2+JWT等 微服务治理:Eureka、Zuul、Hystrix、Spring Cloud Config等 已经实现的功能 CMS管理:页面增删改查,页面预览,页面发布 课程管理:...
1、通过spring security实现的RBAC权限的模型基础上实现权限、角色、资源的管理,实现根据数据库动态分配权限的功能,对未登录及未授权的操作进行拦截。在用户管理中心,管理员可添加用户代替了自行注册方式。 2、...
可以具有许多与之相关联的,并且可以具有与之相关联的许多,这些最后作为JWT令牌中的权限列表添加。 首先,我们必须生成一个KeyStore文件。 为此,请执行以下命令: keytool -genkeypair -alias jwt -keyalg RSA ...
MySQL基于关系型数据库模型,数据以表格形式组织,并通过预定义的键(如主键、外键)在表之间建立关联。它完全支持结构化查询语言(SQL),允许用户进行数据查询、插入、更新、删除、创建和管理数据库结构等操作。...
我们以角色表为中间表,关联起来用户表和功能权限表... security在初始化时会读入全部的权限设计.... 比如url--->{functionid} //字符串-->集合的 Map 用户登录时会保存一个用户的{functionids} 最后用户每访问一...
1、通过spring security实现的RBAC权限的模型基础上实现权限、角色、资源的管理,实现根据数据库动态分配权限的功能,对未登录及未授权的操作进行拦截。在用户管理中心,管理员可添加用户代替了自行注册方式。 <br...
系统前端采用 View UI 组件库,后端集成MyBatisPlus连接MySQL数据库,采用Spring Security做权限控制。 超市账单管理系统采用了基于角色的访问控制,角色和菜单关联,一个角色可以配置多个菜单权限;然后再将用户和...
本项目将对用户、角色、权限三者之间的关联状态概念交给系统管理员与数据库,对外依然具有RBAC的概念。但是在项目的权限管理中,项目只维护用户与权限的关系。 当用户登录成功后立即在数据库查询该用户所具有的角色...
SSM_Maneger_DEMO SQL文件 为ssm1.sql,直接导入到数据库即可 基于 SSM的后台管理系统DEMO(Maven构建) ...方法级权限关联与控制(运用Sercurity标签等技术) 前端使用AdminLTE静态页面模板以及jque
springboot,springsecurity,mybatis,thymeleaf,activemq,redis单机、哨兵、集群,html5兼容,layuimini,jquery,mysql5.6 实现主从数据库切换 上传案例在userList.html中,上传页面userUpload.html,窗体全屏打开也是在...
前后端分离,基于vue2,uniapp,vue-cli,springboot,springsecurity,mybatisplus,mysql初步实现物业管理APP前端界面,后台管理界面,后台系统 MySQL 是一款广受欢迎的开源关系型数据库管理系统(RDBMS),由...
2. **客户管理**:系统能够记录客户的基本信息,包括姓名、联系方式、身份证号等,并与客户入住的房间相关联。 3. **预订与入住**:系统提供房间预订功能,并可处理实际入住时的房间分配和客户登记。 4. **收费结算*...
1. **学籍信息管理**:系统能够记录和管理学生的基本信息,包括姓名、学号、专业等,并与学生的学历证明信息关联。 2. **学历证明生成**:系统支持生成电子版的学历证明,包含必要的认证信息和防伪标识。 3. **证明...
基于 SpringBoot3 + Vue3 + TypeScript+ Mysql + Redis + RabbitMQ + SpringSecurity 的 MySQL 是一款广受欢迎的开源关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,现隶属于美国甲骨文公司(Oracle)。...
系统的安全管理由Spring Security 3提供配置及管理,非常容易与第三方的用户或认证平台进行整合,如与CAS服务器作统一认证,只需要加上新的配置模块即可实现,不影响系统现有的功能模块。大大满足了各种不同系统的...
数据库表 :user --用户表*name*pwd*roleid //关键是这个属性role --角色表*id //角色id*roleName//角色名字function*id//功能表id*roleid//角色id*url//相应的路径重点我们以角色表为中间表,关联起来用户表和功能...
DbHelperV2 - Teddy的通用数据库访问组件设计和思考 也论该不该在项目中使用存储过程代替SQL语句 如何使数据库中的表更有弹性,更易于扩展 存储过程——天使还是魔鬼 如何获取MSSQLServer,Oracel,Access中的数据字典...