Spring Security(基于RBAC模型的权限控制框架)搭建

什么是RBAC模型:

概念

权限管理,这是每个软件系统都会涉及到的,而且权限管理的需求本质往往都是一样,不同的角色拥有不同的权限,只要你充当了某个角色,你就拥有了相对应的功能。

RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联

简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。

这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般都是多对多的关系

 

简介

https://docs.spring.io/spring-security/site/docs/4.2.10.RELEASE/guides/html5/helloworld-xml.html

SpringSecurity融合Spring技术栈,提供JavaEE应 用的整体安全解决方案

Spring Security为基于Java EE的企业软件应用提供全面的安全服务

Spring Security只需要少量配置,就能构建一个强大的安全的应用系统。  

目前市面上受欢迎的两个安全框架:Apache Shiro、SpringSecurity;

SpringSecurity可以无缝整合Spring应用,具有强大的自动化web安全管控功能。而Shiro是一个轻量级强大的安全框架,可以脱离web应用来提供安全管控,但是对于web的一些定制安全需要手动编写;SpringBoot底层默认整合SpringSecurity作为安全框架,所以我们推荐web应用使用SpringSecurity来控制安全;

概念

认证

authentication:身份验证

“身份验证”是指建立主体(principal)的过程,主体就是他们声称是谁(“主体”通常指用户设备或在应用程序中可以执行动作的其他系统)。也就是“证明你是谁

授权

authorization:授权

“授权”是指确定主体(principal是否被允许执行系统中某个动作的过程。 也就是“你能做什么!”

为了达到“授权”决策(安全框架决定你是否有权限做此事),“身份验证”(authentication)过程已经建立了主体的身份(Principal)

使用方式:

       细分角色和权限,并将用户、角色、权限和资源均采用数据库存储,并且自定义过滤器,代替原有的FilterSecurityInterceptor过滤器, 并分别实现AccessDecisionManager、InvocationSecurityMetadataSourceService和UserDetailsService,并在配置文件中进行相应配置。

在原有项目中实现Spring Security权限控制:

1.在parent中添加spring security的依赖

<!-- spring-security依赖包 -->
			<dependency>
				<groupId>org.springframework.security</groupId>
				<artifactId>spring-security-web</artifactId>
				<version>${spring-security.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.security</groupId>
				<artifactId>spring-security-config</artifactId>
				<version>${spring-security.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.security</groupId>
				<artifactId>spring-security-taglibs</artifactId>
				<version>${spring-security.version}</version>
			</dependency>

2.在web.xml中配置spring Security的过滤器进行控制

<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

3.填写config配置类

package com.atguigu.atcrowdfunding.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.AccessDeniedHandler;

@Configuration // 把该类当成配置文件
@EnableWebSecurity // 开启SpringSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)//开启细粒度权限
public class AtcrowdfundingSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private UserDetailsService userDetailsService;
	
	// 认证与授权
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
	   auth.userDetailsService(userDetailsService);
	
	}

	// 配置信息
	@Override
	protected void configure(HttpSecurity http) throws Exception {

		http.authorizeRequests()
				// 放行的请求
				.antMatchers("/static/**", "/welcome.jsp", "/login", "/index").permitAll()
				// 剩下的请求必须验证
				.anyRequest().authenticated();

		// 自定义登录页面
		http.formLogin().loginPage("/login")
		.usernameParameter("loginacct").
		passwordParameter("userpswd")// 登录参数的属性名称
		.loginProcessingUrl("/doLogin")// 登录的跳转路径
		.defaultSuccessUrl("/main");// 跳转的页面

		// 禁用csrf
		http.csrf().disable();// 暂时

//		//出现异常显示的页面
		http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {

			@Override
			public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
				String header = request.getHeader("X-Requested-With");
				if("XMLHttpRequest".equals(header)) {
					response.getWriter().print("403");
				}else {
					request.getRequestDispatcher("/WEB-INF/jsp/error/error403.jsp").forward(request, response);;
				}
			}
		});

	}

}

4.实现查询数据库进行用户权限认证:


import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import com.atguigu.atcrowdfunding.bean.TAdmin;
import com.atguigu.atcrowdfunding.bean.TAdminExample;
import com.atguigu.atcrowdfunding.bean.TAdminExample.Criteria;
import com.atguigu.atcrowdfunding.bean.TPermission;
import com.atguigu.atcrowdfunding.bean.TRole;
import com.atguigu.atcrowdfunding.mapper.TAdminMapper;
import com.atguigu.atcrowdfunding.mapper.TPermissionMapper;
import com.atguigu.atcrowdfunding.mapper.TRoleMapper;

//实现查询数据库的用户权限的认证
@Component
public class MyUserDetailsService  implements UserDetailsService{

	@Autowired
	private TAdminMapper tAdminMapper;
	
	@Autowired
	private TRoleMapper tRolemapper;
	
	@Autowired
	private TPermissionMapper tPermissionMapper;
	
	//查询用户的角色和权限数据
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        TAdminExample example=new TAdminExample();
        Criteria criteria = example.createCriteria();
		criteria.andUsernameEqualTo(username);
//根据用户名查询用户的信息
		List<TAdmin> list = tAdminMapper.selectByExample(example);
		 TAdmin tAdmin=null;
		if(list!=null&&list.size()==1) {
			tAdmin=list.get(0);
		}
		
		//查询用户的角色
		List<TRole> roleList=tRolemapper.queryRoleByAdminId(tAdmin.getId());
		List<TPermission>permissionList=tPermissionMapper.queryPermissionByAdminId(tAdmin.getId());
		
		//查询用户的角色对应的权限
		//List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_初级程序员","ROLE_中级程序员");
		
		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		for (TRole role : roleList) {
			authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
		}
		for (TPermission permission : permissionList) {
			authorities.add(new SimpleGrantedAuthority(permission.getName()));
		}
		
		return new User(tAdmin.getLoginacct(), tAdmin.getUserpswd(), authorities);
	}

}

6.对权限控制进行细粒度控制:(添加注解).

@EnableWebSecurity:开启 Spring Security 注解

@EnableGlobalMethodSecurity(prePostEnabled=true):开启全局的细粒度方法级别权限控制功能

 @PreAuthorize:方法执行前检查

hasRole是角色,hasAuthority是具体的操作,这两个都可以是多个,细粒度控制可以具体到每一个角色的具体操作步骤。动态的不影响项目代码的逻辑结构。

注意事项:

   在使用Springsecurity的细粒度控制时由于Springsecurity是被Spring扫描的,而controller是被SpringMVC扫描的,父不能访问子容器中的内容,所以细粒度注解不能生效,需要在web.xml中更改配置

发布了126 篇原创文章 · 获赞 6 · 访问量 3764

猜你喜欢

转载自blog.csdn.net/qq_40244391/article/details/103292341