一、什么是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:创建用于测试的视图页面
页面效果如下
登录首页
拒绝访问页面
用户登录界面
用户注册界面