Spring Security在Spring Boot中的讲解与实战(附源码)

觉得有帮助请点赞关注收藏~~~

一、什么是Spring Security

Spring Security是一个专门针对Spring应用系统的安全框架,充分利用了Spring框架的依赖注入和AOP功能,为Spring应用系统提供安全访问控制解决方案。

在Spring Security安全框架中,有两个重要概念。一个是授权(authorization),另一个是认证(ahtuentication)。授权即确定用户在当前应用系统下所拥有的功能权限。认证即确认用户访问当前系统的身份

二、Spring Security的基本使用

1:适配器

Spring Security为Web应用提供了一个适配器类WebSecurityConfigurerAdapter 该类实现了WebSecurityConfigurer<WebSecurity>接口,并提供了两个configure方法用于认证和授权操作

2:用户认证

使用AuthenticationManagerBuilder的inMemoryAuthentication()方法可以添加在内存中的用户,并给用户 指定角色权限

3:请求授权

常用方法如下

 三、Spring Boot对Spring Security的支持

在Spring Boot应用中 只需引入spring-boot-starter-security依赖即可使用Spring Security安全框架,这是因为Spring Boot对Spring Security提供了自动配置功能。

接下来通过使用基于Spring Data JPA的Spring Security安全框架来进行实战

1:修改pom.xml文件 添加以下内容

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.45</version>

</dependency>

2:配置application.properties文件

server.servlet.context-path=/ch7_1
###
##数据源信息配置
###
#数据库地址
spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=utf8
#数据库用户名
spring.datasource.username=root
#数据库密码
spring.datasource.password=root
#数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
####
#JPA持久化配置
####
#指定数据库类型
spring.jpa.database=MYSQL
#指定是否在日志中显示SQL语句
spring.jpa.show-sql=true
#指定自动创建、更新数据库表等配置,update表示如果数据库中存在持久化类对应的表就不创建,不存在就创建对应的表
spring.jpa.hibernate.ddl-auto=update
#让控制器输出的JSON字符串格式更美观
spring.jackson.serialization.indent-output=true 
spring.thymeleaf.cache=false
logging.level.org.springframework.security=trace

3:创建用户和权限 持久化的实体类

用户代码如下

package com.ch.ch7_1.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@Entity
@Table(name = "user")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
public class MyUser implements Serializable{
	private static final long serialVersionUID = 1L;
  	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password; 
    //这里不能是懒加载lazy,否则在MyUserSecurityService的loadUserByUsername方法中获得不到权限
    @ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "user_authority",joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "authority_id"))
    private List<Authority> authorityList;
    
    //repassword不映射到数据表
    @Transient
    private String repassword;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public List<Authority> getAuthorityList() {
		return authorityList;
	}
	public void setAuthorityList(List<Authority> authorityList) {
		this.authorityList = authorityList;
	}
	public String getRepassword() {
		return repassword;
	}
	public void setRepassword(String repassword) {
		this.repassword = repassword;
	}
}

权限代码如下

package com.ch.ch7_1.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@Entity
@Table(name = "authority")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
public class Authority implements Serializable{
	private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(nullable = false)
    private String name;
    @ManyToMany(mappedBy = "authorityList")
    @JsonIgnore
    private List<MyUser> userList;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<MyUser> getUserList() {
		return userList;
	}
	public void setUserList(List<MyUser> userList) {
		this.userList = userList;
	}
}

4:创建数据访问层接口

package com.ch.ch7_1.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ch.ch7_1.entity.MyUser;
public interface MyUserRepository extends JpaRepository<MyUser, Integer>{
	//根据用户名查询用户,方法名命名符合Spring Data JPA规范
	MyUser findByUsername(String username);
}

5:创建业务层

接口代码如下

package com.ch.ch7_1.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.ui.Model;
import com.ch.ch7_1.entity.MyUser;
public interface UserService {
	public String register(MyUser userDomain);
	public String loginSuccess(Model model);
	public String main(Model model);
	public String deniedAccess(Model model);
	public String logout(HttpServletRequest request, HttpServletResponse response);
}

实现类代码如下

package com.ch.ch7_1.service;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import com.ch.ch7_1.entity.Authority;
import com.ch.ch7_1.entity.MyUser;
import com.ch.ch7_1.repository.MyUserRepository;
@Service
public class UserServiceImpl implements UserService{
	@Autowired
	private MyUserRepository myUserRepository;
	/**
	 * 实现注册
	 */
	@Override
	public String register(MyUser userDomain) {
		String username = userDomain.getUsername();
		List<Authority> authorityList = new ArrayList<Authority>();
		//管理员权限
		if("admin".equals(username)) {
			Authority a1 = new Authority();
			Authority a2 = new Authority();
			a1.setId(1);
			a1.setName("ROLE_ADMIN");
			a2.setId(2);
			a2.setName("ROLE_DBA");
			authorityList.add(a1);
			authorityList.add(a2);
		}else {//用户权限
			Authority a1 = new Authority();
			a1.setId(3);
			a1.setName("ROLE_USER");
			authorityList.add(a1);
		}
		userDomain.setAuthorityList(authorityList);
		//加密密码
		String secret  = new BCryptPasswordEncoder().encode(userDomain.getPassword());
		userDomain.setPassword(secret);
		MyUser mu = myUserRepository.save(userDomain);
		if(mu != null)//注册成功
			return "/login";
		return "/register";//注册失败
	}
	/**
	 * 用户登录成功
	 */
	@Override
	public String loginSuccess(Model model) {
		model.addAttribute("user", getUname());
		model.addAttribute("role", getAuthorities());
		return "/user/loginSuccess";
	}
	/**
	 * 管理员登录成功
	 */
	@Override
	public String main(Model model) {
		model.addAttribute("user", getUname());
		model.addAttribute("role", getAuthorities());
		return "/admin/main";
	}
	/**
	 * 注销用户
	 */
	@Override
	public String logout(HttpServletRequest request, HttpServletResponse response) {
		//获得用户认证信息
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(authentication != null) {
			//注销
			new SecurityContextLogoutHandler().logout(request, response, authentication);
		}
		return "redirect:/login?logout";
	}
	/**
	 * 没有权限拒绝访问
	 */
	@Override
	public String deniedAccess(Model model) {
		model.addAttribute("user", getUname());
		model.addAttribute("role", getAuthorities());
		return "deniedAccess";
	}
	/**
	 * 获得当前用户名称
	 */
	private String getUname() {
		return SecurityContextHolder.getContext().getAuthentication().getName();
	}
	/**
	 * 获得当前用户权限
	 */
	private String getAuthorities() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		List<String> roles = new ArrayList<String>();
		for (GrantedAuthority ga : authentication.getAuthorities()) {
			roles.add(ga.getAuthority());
		}
		return roles.toString();
	}
}

此处代码太多 需要源码请点赞关注收藏后评论区留言或私信博主

6:创建控制器类

7:创建应用的安全控制相关实现

8:创建用于测试的视图页面

页面效果如下

登录首页

拒绝访问页面 

 用户登录界面

 用户注册界面

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

showswoller

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值