第八章、角色管理

在第七章的基础上进行开发

一、建立权限(角色)的实体

二、建立用户和权限的关系

三、创建用户时,关联角色

四、修改用户的角色

五、初始化权限(角色)、用户的数据

首先在项目的pom.xml文件中添加如下依赖

<!-- Spring Security -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!--对Thymeleaf添加Spring Security标签支持-->
<dependency>
	<groupId>org.thymeleaf.extras</groupId>
	<artifactId>thymeleaf-extras-springsecurity4</artifactId>
	<version>3.0.2.RELEASE</version>
</dependency>

权限实体  Authority  实现GrantedAuthority接口,实现getAuthority方法来替换getName方法

package com.waylau.spring.boot.blog.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.springframework.security.core.GrantedAuthority;
/**
 * 权限实体
 * @author Administrator
 *
 */
@Entity
public class Authority implements GrantedAuthority{

	private static final long serialVersionUID = 1L;

	@Id//主键
	@GeneratedValue(strategy = GenerationType.IDENTITY)//主键的生成策略(自增)
	private Long id;//实体一个唯一标识
	
	@Column(nullable = false)//映射为字段 值不能为空
	private String name;
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Override//覆盖getName方法
	public String getAuthority() {
		// TODO Auto-generated method stub
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

对原来的User实体类做修改 实现UserDetails接口

package com.waylau.spring.boot.blog.domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.validation.constraints.Size;
import javax.persistence.JoinColumn; 


import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * 用户实体
 * @author Administrator
 * Spring注解 @NotBlank,@NotNull,@NotEmpty
 */
@Entity//实体
public class User implements UserDetails{
	
	private static final long serialVersionUID = 1L;

	@Id//主键
	@GeneratedValue(strategy = GenerationType.IDENTITY)//主键的生成策略(自增)
	private Long id;//实体一个唯一标识
	
	@NotEmpty(message = "姓名不能为空")//不能为null,也不能为空
	@Size(min = 2, max = 20)
	@Column(nullable = false, length = 20)//映射为字段 值不能为空
	private String name;
	
	@NotEmpty(message = "邮箱不能为空")
	@Size(max = 50)
	//nullable表示该字段是否可以为null值,默认为true unique表示该字段是否为唯一标识,默认为false
	@Email(message = "邮箱格式不对")
	@Column(nullable = false, length = 50, unique = true)
	private String email;
	
	@NotEmpty(message = "账号不能为空")
	@Size(min = 3, max = 20)
	@Column(nullable = false, length = 20, unique = true)
	private String username;//用户账号  用户登录的唯一标识
	
	@NotEmpty(message = "密码不能为空")
	@Size(max = 100)
	@Column(length = 100)//字段长度
	private String password;//密码
	
	@Column(length = 200)
	private String avatar;//头像信息
	
	/**
	 *  CascadeType.DETACH  级联脱管/游离操作。如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联
	 *  FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载
	 *  @JoinTable name属性为连接两个表的表名称(即中间表)。若不指定,则使用默认的表名称如下所示 “表名1”+“_”+“表名2”
	 *  joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") user_id为外键关联到user表中的id字段
	 *  inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id") authority_id为外键关联到authority表中的id字段
	 *  注意:@JoinColumn 要手动导入
	 */
	@ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.EAGER)//多对多关系
    @JoinTable(name = "user_authority", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 
        inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id"))
	private List<Authority> authorities;//用户和权限的关系
	
	protected User(){}//无参构造    设为protected防止直接使用
	
	public User(Long id, String name, String username, String email) {
		this.id = id;
		this.name = name;
		this.email = email;
		this.username = username;
	}

	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	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 String getAvatar() {
		return avatar;
	}
	public void setAvatar(String avatar) {
		this.avatar = avatar;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", email=" + email + ", username=" + username + ", password="
				+ password + ", avatar=" + avatar + "]";
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		//  需将 List<Authority> 转成 List<SimpleGrantedAuthority>,否则前端拿不到角色列表名称
        List<SimpleGrantedAuthority> simpleAuthorities = new ArrayList<>();
        for(GrantedAuthority authority : this.authorities){
            simpleAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
        }
        return simpleAuthorities;
	}
	
	public void setAuthorities(List<Authority> authorities){
		this.authorities = authorities;
	}
	
	//账号未过期
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	//账号未锁定
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	//凭证未过期
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	//是否启用
	@Override
	public boolean isEnabled() {
		return true;
	}
	
}

AuthorityRepository如下

package com.waylau.spring.boot.blog.domain;

import org.springframework.data.jpa.repository.JpaRepository;
/**
 * Authority 仓库
 * @author Administrator
 *
 */
public interface AuthorityRepository extends JpaRepository<Authority, Long>{

}

服务接口AuthorityService

package com.waylau.spring.boot.blog.service;

import com.waylau.spring.boot.blog.domain.Authority;

/**
 * Authority 服务接口
 * @author Administrator
 *
 */
public interface AuthorityService {
	/**
	 * 根据ID查询Authority
	 * @param id
	 * @return
	 */
	Authority getAuthorityById(Long id);
}

服务实现类 AuthorityServiceImpl

package com.waylau.spring.boot.blog.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.waylau.spring.boot.blog.domain.Authority;
import com.waylau.spring.boot.blog.domain.AuthorityRepository;
/**
 * Authority 服务接口的实现
 * @author Administrator
 *
 */
@Service
public class AuthorityServiceImpl implements AuthorityService{

	@Autowired
	private AuthorityRepository authorityRepository;
	
	@Override
	public Authority getAuthorityById(Long id) {
		return authorityRepository.findOne(id);
	}

}

修改UserController 自动注入 

@Autowired
private AuthorityService authorityService;

修改方法如下

/**
 * 保存或修改用户
 * @param user
 * @return
 */
@PostMapping
public ResponseEntity<Response> saveOrUpdateUser(User user, Long authorityId){
	List<Authority> authorities = new ArrayList<Authority>();
	authorities.add(authorityService.getAuthorityById(authorityId));
	user.setAuthorities(authorities);
	try{
		userService.saveOrUpdateUser(user);
	} catch (ConstraintViolationException e) {
		return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
	}
	return ResponseEntity.ok().body(new Response(true, "处理成功", user));
}

修改MainController 注册方法

private static final Long ROLE_USER_AUTHORITY_ID = 2L;//注册用户是博主的权限

@Autowired
private AuthorityService authorityService;

/**
 * 注册用户 
 * @param user
 * @return
 */
@PostMapping("/register")
public String registerUser(User user){
	//赋予权限
	List<Authority> authorities = new ArrayList<Authority>();
	authorities.add(authorityService.getAuthorityById(ROLE_USER_AUTHORITY_ID));
	user.setAuthorities(authorities);
	
	userService.registerUser(user);
	return "redirect:/login";//成功后跳转到登录页面
}

安全配置类如下

package com.waylau.spring.boot.blog.config;

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;
/**
 * 安全配置类
 */
@EnableWebSecurity//启用web安全
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	/**
	 * 自定义配置
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/css/**", "/js/**", "/fonts/**", "/index").permitAll();//都可以访问
	}
}

前端修改三个页面

list.html中添加权限的显示

在add.html中添加(因为固定设置了两种角色 管理员和博主)

<div class="form-group">
	<label for="authorities" class="col-form-label">角色</label>
	<select id="authorities" name="authorityId" class="form-control form-control-chosen" data-placeholder="请选择">
	  <option value="1">管理员</option>
	  <option value="2">博主</option>
	</select>
</div>

在edit.html中添加

<div class="form-group">
	<label for="authorities" class="col-form-label">角色</label>
	<select id="authorities" name="authorityId" class="form-control form-control-chosen" data-placeholder="请选择">
	  <option value="1" data-th-selected="${#strings.contains(userModel.user.authorities[0],'ROLE_ADMIN')}">管理员</option>
	  <option value="2" data-th-selected="${#strings.contains(userModel.user.authorities[0],'ROLE_USER')}">博主</option>
	</select>
</div>

初始化数据(采用脚本)

当启动服务的时候会自动读取import.sql

INSERT INTO user (id, username, password, name, email) VALUES (1, 'admin', '123456', '老卫', 'i@waylau.com');
INSERT INTO user (id, username, password, name, email)  VALUES (2, 'waylau', '123456', 'Way Lau', 'waylau@waylau.com');

INSERT INTO authority (id, name) VALUES (1, 'ROLE_ADMIN');
INSERT INTO authority (id, name) VALUES (2, 'ROLE_USER');

INSERT INTO user_authority (user_id, authority_id) VALUES (1, 1);
INSERT INTO user_authority (user_id, authority_id) VALUES (2, 2);

数据库如下

关联表的外键设置

测试页面如下  http://localhost:8080/admins

执行添加功能(修改功能类似)

结果如下

测试注册功能

注册完成后会跳转到登录页面,此时我们直接查看数据/admins

默认注册的用户赋予了博主的权限,也就是常量

private static final Long ROLE_USER_AUTHORITY_ID = 2L;//注册用户是博主的权限

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

荒--

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

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

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

打赏作者

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

抵扣说明:

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

余额充值