SpringSecurity整合到SSM框架中

3 篇文章 0 订阅
1 篇文章 0 订阅

一、在pom.xml导入SpringSecurity对应的jar包

1. 在父工程中引入spring-security依赖

	<properties>
		......
		<!-- 控制引入spring-security依赖的版本号 -->
		<spring-security.version>4.2.10.RELEASE</spring-security.version>
	</properties>
	
	<dependencies>
		......
		<!-- 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>
	</dependencies>

2. 在子工程(我这里是在Service层与Web层引入)中声明spring-security依赖

	<dependencies>
		......
		<!-- 引入spring-security依赖包,不需要指明版本号,由父工程控制 -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
		</dependency>
	</dependencies>

二、在web工程中的web.xml配置SpringSecurity对应的过滤器(这里需要将Spring容器与SpringMVC容器整合成一个容器,即SpringMVC容器)

	<!-- springSecurity过滤器 -->
	<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>

三、编写SpringSecurity配置类


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.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;

//SpringSecurity的配置文件
@Configuration											//表示这个一个SpringSecurity的配置文件
@EnableWebSecurity										//开启 Spring Security 注解
@EnableGlobalMethodSecurity(prePostEnabled=true)		//开启全局的细粒度方法级别权限控制功能
public class AtCrowdFundingSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	UserDetailsService userDetailsService;
	
//	@Autowired
//	private PasswordEncoder passwordEncoder;

	//基本配置
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
		//开放权限("welcome.jsp"只能访问这个页面,不能访问这个页面的所有转发和请求,"/welcome.jsp"则可以)
		.antMatchers("/static/**","welcome.jsp","/login").permitAll()
		//除以上资源都得认证后才能访问
		.anyRequest().authenticated();
		//如果没有登录就去访问没有权限的页面或者请求,指定跳转到自定义登录页面
		http.formLogin().loginPage("/login")
		//自定义表单的action请求的路径
		.loginProcessingUrl("/doLogin")
		//自定义表单的username的name
		.usernameParameter("loginacct")
		//自定义表单的password的name
		.passwordParameter("userpswd")
		.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");
				//如果有该值则表示这是一个AJAX异步请求
				if("XMLHttpRequest".equals(header)) {
					response.getWriter().print("403");
				}else {//如果没有该值则表示这是一个同步请求
					request.getRequestDispatcher("/WEB-INF/jsp/admin/error403.jsp").forward(request, response);
				}
				
			}
		});
	}
	
	//认证和授权的配置
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		//基于数据库的用户认证,需要实现UserDetailsService类
		auth.userDetailsService(userDetailsService)
		//使用BCrypt加密算法
		.passwordEncoder(new BCryptPasswordEncoder());
		//使用自定义的加密算法(MD5)
//		.passwordEncoder(passwordEncoder);
	}

}

四、编写UserDetailsService实现类


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.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 MyUserDetailsServiceImpl implements UserDetailsService{
	
	@Autowired
	private TAdminMapper adminMapper;
	
	@Autowired
	private TRoleMapper roleMapper;
	
	@Autowired
	private TPermissionMapper permissionMapper;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		//首先根据username去查询数据库是否有该用户
		TAdminExample example = new TAdminExample();
		example.createCriteria().andLoginacctEqualTo(username);
		List<TAdmin> admins = adminMapper.selectByExample(example);
		TAdmin admin = null;
		if(admins!=null&&admins.size()==1) {
			admin = admins.get(0);
		}
		//根据adminId去查询该用户拥有的所有角色信息
		Integer adminId = admin.getId();
		List<TRole> roles = roleMapper.queryRolesByAdminId(adminId);
		//根据adminId去查询该用户拥有的所有权限信息
		List<TPermission> permissions = permissionMapper.queryPermissionsByAdminId(adminId);
		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		//将查询的所有角色名字都放入set集合中,注意要加前缀"ROLE_"
		for (TRole role : roles) {
			authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
		}
		//将查询的所有权限名字都放入set集合中
		for (TPermission permission : permissions) {
			authorities.add(new SimpleGrantedAuthority(permission.getName()));
		}
		//返回一个SpringSecurity框架的User类,该类包含了该用户的用户名和加密的密码以及拥有的角色和权限
		return new User(admin.getLoginacct(), admin.getUserpswd(), authorities);
	}

}

五、编写PasswordEncoder实现类(使用MD5加密)


import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import com.atguigu.atcrowdfunding.util.MD5Util;

@Component
public class MyPasswordEncoderImpl implements PasswordEncoder{

	//使用MD5对前端传来的明文密码加密
	@Override
	public String encode(CharSequence rawPassword) {
		String password = MD5Util.digest(rawPassword.toString());
		return password;
	}

	//判断加密后的密文与数据库中的密文是否一样
	@Override
	public boolean matches(CharSequence rawPassword, String encodedPassword) {
		String uiPassword = encode(rawPassword);
		String dbPassword = encodedPassword;
		return dbPassword.equals(uiPassword);
	}

}

六、在Controller对应的映射请求中加上@PreAuthorize(xxx)注解即可

	//添加用户
	@ResponseBody
	@RequestMapping(value="/role/addRole")
	@PreAuthorize("hasRole('PM - 项目经理') AND hasAuthority('user:add')")
	public String saveRole(TRole role) {
		int i = roleService.saveRole(role);
		if(i!=0) {
			return "OK";
		}else {
			return "False";
		}
	}

注:如需要将用户姓名在前端显示,只要在前端加上<security:authentication property=“name”/>即可
如需要在前端根据权限显示对应的按钮、图片等内容时,只需要在标签外边包上<security:authorize access="xxx "></security:authorize>标签,如下图所示,不过都需要先引入springsecurity标签库。

	<!-- 权限控制 -->
	<!-- hasRole('PM - 项目经理')  AND hasRole('SE - 软件工程师'):必须含有这两个角色才能访问 -->
	<!-- hasRole('PM - 项目经理')  OR hasRole('SE - 软件工程师'):有这两个角色中的一个就能访问,也可以同时拥有这两个角色 -->
	<!-- hasRole('PM - 项目经理')  AND hasAuthority('user:add'):必须含有该角色和该权限才能访问 -->
	<!-- hasRole('PM - 项目经理')  OR hasAuthority('user:add'):有这个角色和这个权限中的一个就能访问,也可以同时拥有这个角色和该权限 -->
	<security:authorize access="hasRole('PM - 项目经理')  OR hasRole('SE - 软件工程师')  ">
			<button id="addBtn" type="button" class="btn btn-primary" style="float: right;">
				<i class="glyphicon glyphicon-plus"></i> 新增
			</button>
	</security:authorize>
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值