- 设计数据库
数据库权限概念
角色用户组权限关联
数据库实体图:
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进行比对,为了考虑运行速度的问题,还必须要把所有的浏览权限保存在内存中,否则每次都会从数据库中进行查询,减低了效率
大家都想自定义实现权限验证,这种方法告诉大家了
好了,如果有问题,请留言,由于分析难度比较大,只能慢慢来了
相关推荐
下面将详细阐述如何进行Spring Security的数据库权限管理配置。 1. **配置数据源** 在Spring Security中,我们需要一个数据源来连接到数据库,存储用户、角色和权限信息。在Spring Boot项目中,可以通过...
在处理与数据库交互方面,Spring Security提供了更强大的支持,包括长期的remember-me功能和基于数据库的角色与用户管理API。 24.2. 目标 在原有应用中,用户信息和资源访问控制已经在数据库中管理。目标是将现有...
在这个“springboot springsecurity动态权限控制”的主题中,我们将深入探讨如何在Spring Boot项目中集成Spring Security,实现动态权限控制,让菜单权限的管理更加灵活和高效。 首先,我们需要理解Spring Security...
通过分析这些代码,你可以理解如何将Spring Security与数据库集成,实现动态权限管理。 总的来说,Spring Security的动态授权功能使得权限管理变得更加灵活和高效。通过对源代码的适当修改,我们可以构建一个完全可...
RBAC将权限与角色关联,而EL允许更复杂的条件表达式,如`@PreAuthorize("hasRole('ADMIN') and hasPermission('EDIT_CONTENT')"`。 8. **权限服务和权限表达式** 为了实现更细粒度的权限控制,Spring Security提供...
在这个例子中,我们将探讨如何将Spring Security与MySQL数据库结合使用,通过bean配置来实现用户认证和权限管理。首先,我们需要理解Spring Security的基本架构,它由一系列组件构成,如AuthenticationManager负责...
- 角色权限关联表(role_permissions):定义角色拥有的权限。 **5. 配置 Spring Security** 在 Spring Security 的配置类中,你需要定义认证和授权的规则。例如,使用 `httpSecurity` 配置对象设置登录页面、访问...
在"spring security用数据库的示例"中,我们将深入探讨如何配置Spring Security以使用数据库进行用户管理和权限控制。 首先,Spring Security的核心组件包括Authentication(认证)和Authorization(授权)。认证是...
5. **Role-Based Access Control (RBAC)**:RBAC是一种常用的权限模型,SpringSecurity支持RBAC,允许将权限与角色关联,然后将角色分配给用户。 6. **Expression-Based Access Control (ELBAC)**:除了基于角色的...
在本文中,我们将深入探讨如何使用Spring Boot、Spring Security和MyBatis这三大技术栈来实现用户权限的数据库动态管理。这是一个常见的需求,在许多企业级应用中,动态管理用户权限可以提高系统的灵活性和可扩展性...
2. **SpringSecurity**:SpringSecurity是一个用于保护Web应用的安全框架,提供了身份验证、授权等功能。它通过一系列拦截器对HTTP请求进行过滤,确保只有经过认证和授权的用户才能访问特定资源。在这个项目中,...
首先,SpringSecurity的核心功能包括用户认证、权限授权、会话管理以及防止常见攻击。其中,用户认证涉及验证用户凭据,如用户名和密码,以确定用户的身份。而权限授权则决定了已认证的用户可以访问哪些资源或执行...
**Spring Security数据库认证实例(dao认证)** Spring Security是一个强大且高度可定制的身份验证和访问控制框架,广泛用于Java企业级应用的安全管理。在数据库认证的场景中,Spring Security允许我们存储用户信息和...
后端使用SpringBoot框架进行业务逻辑开发,利用Spring Security实现权限控制。数据库采用MySQL进行数据存储,使用MyBatis进行数据访问。 权限控制模块设计包括用户、角色和权限三个主要模块。用户模块用于管理用户...
标题与描述均提到了“Spring Security 2 配置说明”,这表明文章旨在阐述Spring Security 2版本的配置细节,尤其是对于那些希望深入了解并正确应用该框架的安全特性开发者们。以下将基于给定的部分内容,深入解析...
在本笔记中,我们将深入探讨SpringSecurity的核心概念、配置以及如何与SpringBoot结合使用。 1. **SpringSecurity核心概念** - **Filter Chain**: SpringSecurity通过一系列过滤器实现其安全功能,这些过滤器构成...
本篇将深入探讨如何利用Spring Security进行角色权限校验,并动态地从数据库中查询用户是否具有访问特定接口的权限。 首先,我们需要理解Spring Security的基本架构。它主要包括四个主要组件:认证(Authentication...
在这个"Spring Security2配置"的主题中,我们将深入探讨如何配置Spring Security来保护我们的应用程序,以及它的一些核心概念。 首先,让我们理解Spring Security的基本组件。`Users.java`、`Roles.java`暗示了用户...
在权限管理系统中,通常会设计几个核心表,如用户表(User)、角色表(Role)、权限表(Permission)以及角色-权限关联表(Role_Permission)、用户-角色关联表(User_Role)。这些表之间的关系是一对多和多对多,...
通过这个Spring Security实战例子,你可以深入了解Spring Security的配置、认证和授权机制,以及如何与数据库集成。实践是最好的老师,动手完成这四个小项目将有助于巩固理解,并为你在实际项目中应用Spring ...