spring security
- 权限数据管理(增删改查)。
- 角色数据管理(增删改查、角色关联权限)。
- 用户数据管理(增删改查、用户关联角色)。
导入maven坐标
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<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>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
整合spring
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!--配置哪些资源匿名也可以访问-->
<security:http security="none" pattern="/login.html"/>
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/img/**"/>
<security:http security="none" pattern="/js/**"/>
<security:http security="none" pattern="/plugins/**"/>
<!--
http:用于定义相关权限控制
auto-config:是否自动配置
true:设置为true时框架会提供默认的一些配置,例如提供默认的登录页面、登出 处理等
false:设置为false时需要显示提供登录表单配置,否则会报错
use-expressions:用于指定intercept-url中的access属性是否使用表达式
-->
<security:http auto-config="true" use-expressions="true">
<security:headers>
<!--设置在页面可以通过iframe访问受保护的页面,默认不允许访问-->
<security:frame-options policy="SAMEORIGIN"/>
</security:headers>
<!--intercept-url:定义一个拦截规则 pattern:对哪些url进行权限控制
access:在请求对应的URL时需要什么权限,默认配置时它应该是一个以逗号分隔的角色列 表, 请求的用户只需拥有其中的一个角色就能成功访问对应的URL -->
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>
<!--只要认证通过就可以访问-->
<security:intercept-url pattern="/pages/**" access="isAuthenticated()"/>
<!--form-login:定义表单登录信息-->
<security:form-login login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/pages/main.html"
authentication-failure-url="/login.html"/>
<!--
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁用(403)
-->
<security:csrf disabled="true"/>
<!--
logout:退出登录
logout-url:退出登录后操作对应的请求路径
logout-success-url:退出登录后的跳转页面
-->
<security:logout logout-url="/logout.do" logout-success-url="/login.html" invalidate-session="true"/>
</security:http>
<!--authentication-manager:认证管理器,用于处理认证操作 -->
<security:authentication-manager>
<!--authentication-provider:认证提供者,执行具体的认证逻辑 -->
<security:authentication-provider user-service-ref="springSecurityUserServiceImpl">
<!--指定对密码进行加密的对象-->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!--配置密码加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--开启注解方式权限控制-->
<security:global-method-security pre-post-annotations="enabled"/>
<!--注入springSecurityUserServiceImpl对象-->
<bean id="springSecurityUserServiceImpl" class="com.itheima.service.SpringSecurityUserServiceImpl"/>
</beans>
用户的认证和授权controller层
- 创建一个类实现UserDetailsService接口重写loadUserByUsername()方法
- 通过dubbo调用zookeeper注册中心的UserService
- 根据传递的username调用userService查询用户信息
- 如果查出来是null则返回空
- 如果不为空创建一个权限集合范围为
GrantedAuthorty
- 根据查询到的用户的信息获取用户的角色信息并授予角色
- 遍历角色信息查询用户的权限信息并授予权限
- 创建srping security里面的user对象传入三个参数
用户名、用户的加密密码、授权的集合信息
- 将spring scurity下的user返回
package com.itheima.service;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author 陈朋
* @date 2021/1/7 0007 21:10
*/
public class SpringSecurityUserServiceImpl implements UserDetailsService {
/**
* 使用dubbo通过网络远程调用服务提供方获取用户信息
*/
@Reference
private UserService userService;
/**
* 根据用户名查询数据库获取用户信息
*
* @param username 用户的名称
* @return UserDetails
* @throws UsernameNotFoundException 用户信息找不到异常
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findUserByUsername(username);
if (user==null){
return null;
}
List<GrantedAuthority> list=new ArrayList<>();
//动态为用户授权
//获取用户的角色信息
Set<Role> roles = user.getRoles();
//遍历角色集合,为用户授予角色
for (Role role : roles) {
list.add(new SimpleGrantedAuthority(role.getKeyword()));
//获取角色的权限信息
Set<Permission> permissions = role.getPermissions();
//遍历权限集合,为用户授权
for (Permission permission : permissions) {
//遍历权限集合,为用户授权
list.add(new SimpleGrantedAuthority(permission.getKeyword()));
}
}
return new org.springframework.security.core.userdetails.User(username,user.getPassword(),list);
}
}
service接口以及实现类、mapper接口以及xml文件
package com.itheima.service;
import com.itheima.pojo.User;
/**
* @author 陈朋
* @date 2021/1/7 0007 21:13
*/
public interface UserService {
/**
* 根据用户名查询用户信息
* @param username 用户名
* @return 用户实体类
*/
User findUserByUsername(String username);
}
package com.itheima.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.dao.PermissionDao;
import com.itheima.dao.RoleDao;
import com.itheima.dao.UserDao;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
/**
* 用户服务接口
*
* @author 陈朋
* @date 2021/1/7 0007 21:29
*/
@Service(interfaceClass = UserService.class)
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings("all")
public class UserServiceImpl implements UserService {
@Autowired
private PermissionDao permissionDao;
@Autowired
private RoleDao roleDao;
@Autowired
private UserDao userDao;
/**
* 根据用户名查询数据库获取用户信息关联的角色的信息,同时需要查询角色关联的权限的信息
*
* @param username 用户名
* @return user对象
*/
@Override
public User findUserByUsername(String username) {
//根据用户名查询用户信息
User user = userDao.findUserByUsername(username);
if (user == null) {
//如果用户不存在直接返回null
return null;
}
//获取用户的id
Integer userId = user.getId();
//根据用户的di查对应的角色
Set<Role> roles = roleDao.findByUserId(userId);
//编辑角色信息
for (Role role : roles) {
//获取角色的id
Integer roleId = role.getId();
//根据角色的id查询权限信息
Set<Permission> permissions = permissionDao.findByRoleId(roleId);
//角色关联权限
role.setPermissions(permissions);
}
//用户关联角色
user.setRoles(roles);
return user;
}
}
public interface UserDao {
/**
* 根据用户名查询用户信息
* @param username 用户名
* @return 用户对象
*/
User findUserByUsername(String username);
}
public interface RoleDao {
/**
* 根据用户的id查询角色信息
* @param userId 用户的id
* @return 封装角色的set集合
*/
Set<Role> findByUserId(Integer userId);
}
public interface PermissionDao {
/**
* 根据角色的id查询权限信息
* @param roleId 角色的id
* @return 封装权限信息的set集合
*/
Set<Permission> findByRoleId(Integer roleId);
}
在controller上加权限控制注解
/**
* 根据id删除检查项
*
* @param id 要删除的检查项的id
* @return 封装后的查询结果
*/
@PreAuthorize("hasAuthority('CHECKITEM_DELETE')")
@GetMapping("/delete")
public Result delete(Integer id) {
try {
checkItemService.deleteById(id);
} catch (Exception e) {
e.printStackTrace();
return Result.failed( MessageConstant.DELETE_CHECKITEM_FAIL);
}
return Result.success( MessageConstant.DELETE_CHECKITEM_SUCCESS);
}
echarts简介
概念:最牛逼的图形数据表
- 根据官网五分钟入门
- 连接echatrs入门
项目导入
- 导入echarts.js文件
<script src="../plugins/echarts/echarts.js"></script>
- 导入echarts界面的div
<div class="app-container">
<div class="box">
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="chart1" style="height:600px;"></div>
</div>
前台页面
<!DOCTYPE html>
<html lang="ch">
<head>
<!-- 页面meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>传智健康</title>
<meta name="description" content="传智健康">
<meta name="keywords" content="传智健康">
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../css/style.css">
<script src="../plugins/echarts/echarts.js"></script>
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>统计分析<small>会员数量</small></h1>
<el-breadcrumb separator-class="el-icon-arrow-right" class="breadcrumb">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>统计分析</el-breadcrumb-item>
<el-breadcrumb-item>会员数量</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="app-container">
<div class="box">
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="chart1" style="height:600px;"></div>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
let myChart1 = echarts.init(document.getElementById('chart1'));
// 使用刚指定的配置项和数据显示图表。
//myChart.setOption(option);
axios.get("/report/getMemberReport.do").then((res)=>{
myChart1.setOption(
{
title: {
text: '会员数量'
},
tooltip: {},
legend: {
data:['会员数量']
},
xAxis: {
data: res.data.data.months
},
yAxis: {
type:'value'
},
series: [{
name: '会员数量',
type: 'line',
data: res.data.data.memberCount
}]
});
});
</script>
</html>
后台代码
@GetMapping("/getMemberReport")
public Result getMemberReport() {
Map<String, Object> map = new HashMap<>(2);
List<String> months = new ArrayList<>();
//获取日历对象,得到的时间就是当前时间
Calendar calendar = Calendar.getInstance();
//获取当前日期之前的六个月日期
calendar.add(Calendar.MONTH, -12);
for (int i = 0; i < 12; i++) {
calendar.add(Calendar.MONTH, 1);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM");
Date date = calendar.getTime();
String memberDate = simpleDateFormat.format(date);
months.add(memberDate);
}
//将前六个月注册的会员封装到map集合中
map.put("months", months);
List<Integer> memberCount = memberService.findMemberCountByMonth(months);
map.put("memberCount", memberCount);
if (map.isEmpty()) {
return Result.failed("查询数据失败");
}
return Result.success(MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);
}