博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC+Spring Data JPA+Shiro+EasyUI简单权限管理系统
阅读量:2492 次
发布时间:2019-05-11

本文共 12383 字,大约阅读时间需要 41 分钟。

概述

一直想做一个管理系统,希望它简洁,能做一个demo使用。以后在研究学习的时候,可以在此基础上增加代码。我觉得权限管理系统很值得做,因为涉及关系数据库模式的设计,能学到很多东西。万事开头难,先做个简单的,以后再慢慢完善的。任何事情关键是要做,不能停留在想。

前端

由于之前没有多少前端编程经验,所以做起前端比较吃力。之前前端使用Bootstrap,发现需要自己编写很多前端代码,虽然花费了很多时间,但是页面做起来还是很难看。后来前端选择了EasyUI,发现特别适合做管理页面,也容易上手。当然每个框架都有其局限性,后面使用多了就知道了,就是EasyUI不够灵活,但是现在先用着,以后再选择换其他的。EasyUI官网

MVC

使用主流的SpringMVC,不但功能强大,用起来比较简单方便。

SpringMVC推荐学习网站

持久化

使用Spring Data JPA。这个框架真的很赞,对于简单的业务逻辑,基本不用些SQL代码。最重要的是可以根据接口名自动生成SQL代码,极大的提高了开发效率。参考

同时也配置了Hibernate,虽然现在还没是用,但准备后期和Spring Data JPA配合是用。

权限管理

选择Shiro,简单好用,容易上手。推荐学习网站

权限模型了解

使用预览

注册

这里写图片描述

登录

这里写图片描述

管理后台

这里写图片描述

设置角色

这里写图片描述

授权

这里写图片描述

实体层

以下只是展示了部分关键代码

用户

用户和角色是N-N的关系。

@Entity@Table(name = "sys_user")public class User implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 编号 // 这里不能用CascadeType.ALL @ManyToMany(targetEntity = Role.class, cascade = CascadeType.MERGE, fetch = FetchType.EAGER) @JoinTable(name = "sys_user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id") ) private Set
roles = new HashSet<>(); @Column(unique = true) private String username; // 用户名 private String password; // 密码 private String salt; // 加密密码的盐 private Boolean locked = Boolean.FALSE; private String email; @Column(name = "create_date") @Temporal(TemporalType.TIMESTAMP) private Date createDate = new Date();....

角色

@Entity@Table(name = "sys_role")public class Role implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 编号 @OneToMany(targetEntity = Permission.class, cascade = CascadeType.REFRESH, fetch = FetchType.EAGER) @JoinTable(name = "sys_role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id", unique = true) ) private List
permissions = new ArrayList<>(); private String name; @Column(unique = true) private String role; // 角色标识 程序中判断使用,如"admin" private String description; // 角色描述,UI界面显示使用

权限

权限是资源和操作的组合。也就是说一个权限意味着对一个资源的多个操作。

@Entity@Table(name = "sys_permission")public class Permission implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(targetEntity = Resource.class, cascade = CascadeType.REFRESH, fetch = FetchType.EAGER) @JoinColumn(name = "resource_id", referencedColumnName = "id") private Resource resource; @ManyToMany(targetEntity = Operation.class, cascade = CascadeType.REFRESH, fetch = FetchType.EAGER) @JoinTable(name = "sys_permission_operation", joinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "operation_id", referencedColumnName = "id") ) private Set
operations = new HashSet<>(); private String name; private String description;

资源

@Entity@Table(name = "sys_resource")public class Resource implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 编号 private String name; // 资源名称 @Column(unique = true) private String identity;// 资源类型

操作

@Entity@Table(name = "sys_operation")public class Operation implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 编号 private String name; // 操作名称 @Column(unique = true) private String operation;// 操作标识 private String description;

简洁易用的Spring Data JPA

Spring Data可以通过解析方法名创建查询。比如方法是findByUsername(String username),则Spring Data会自动生成SQL语句select * from 表名 where username= username.所以你对于简单的操作,你只要按照Srping Data约定写出对应的方法名,Spring Data就能自动创建SQL语句,基本不需要你写SQL语句。

一般定义DAO层时,继承一个Spring Data的基本接口,比如JpaRepository,该接口能可以帮你实现增删查改的功能外,还可以帮你做分页查询和排序。

import org.springframework.data.jpa.repository.JpaRepository;import com.myweb.entity.User;public interface UserDao extends JpaRepository
{
User findByUsername(String username);}

使用时,直接注入就可以了

@Inject    private UserDao userDao;

Shiro认证与授权

shiro比Spring Security简单,在实现认证授权的时候,继承一个Realm类然后扩展,这里使用AuthorizingRealm。

Realm在shiro中类似数据源,认证和授权的数据就依靠它。

public class UserRealm extends AuthorizingRealm {
@Inject private UserService userService; @Inject private UserDao userDao; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 授权 String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(userService.getStringRoles(username)); authorizationInfo.setStringPermissions(userService.getStringPermissions(username)); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // 认证 String username = (String) authenticationToken.getPrincipal(); User user = userDao.findByUsername(username); // 查出是否有此用户 if (user == null) { throw new UnknownAccountException();// 没找到帐号 } if (Boolean.TRUE.equals(user.getLocked())) { throw new LockedAccountException(); // 帐号锁定 } // 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), getName()); return authenticationInfo; }}

认证

需要SecurityUtils返回一个Subject,然后通过用户名和密码创建Token,使用这个Token登录验证。Subject 是 Shiro 的核心对象,基本所有身份验证、授权都是通过 Subject 完成。

@RequestMapping(value = "/login", method = RequestMethod.POST)    public ModelAndView login(User user) {        ModelAndView mv = new ModelAndView();        try {            Subject subject = SecurityUtils.getSubject();            UsernamePasswordToken authenticationToken = new UsernamePasswordToken(user.getUsername(),                    user.getPassword());            subject.login(authenticationToken);        } catch (AuthenticationException e) {            e.printStackTrace();            mv.setViewName("redirect:/unauthorized");            return mv;        }        mv.setViewName("redirect:/index");        return mv;    }

授权

采用注解形式,简单方便

@RequiresPermissions("user:create")    @RequestMapping(value = "/save", method = RequestMethod.POST)    @ResponseBody    public String saveUser(@RequestParam String username, @RequestParam String password, @RequestParam String email,            @RequestParam(value = "roles", required = false) List
roleIds) { User user = new User(); user.setUsername(username); user.setPassword(password); user.setEmail(email); List
roles = roleDao.findAll(roleIds); user.setRoles(new HashSet<>(roles)); userService.save(user); return "OK"; }

支持注解需要配置

XML配置

项目整体配置

web.xml:

myweb
/WEB-INF/jsp/login.jsp
contextConfigLocation
classpath*:config/spring-*.xml
org.springframework.web.context.ContextLoaderListener
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/*
openSession
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
singleSession
true
flushMode
AUTO
openSession
/*
myweb
myweb
springMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath*:config/spring-mvc.xml
1
springMVC
/
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*

配置SpringMVC

spring-mvc.xml:

com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/myweb
root
apolication/json; charset=UTF-8

shiro在Spring配置

spring-shiro-web.xml:

/static/** = anon /api/user/login = anon /api/user/register* = anon /unauthorized = anon /** = authc

hibernate配置

hibernate.cfg.xml

org.hibernate.dialect.MySQLDialect
com.mysql.jdbc.Driver
jdbc:mysql://localhost/myweb
root
jiangyu
false
update
true
true
50
30
org.hibernate.connection.C3P0ConnectionProvider
30
2
30000
120
180
3
50
1
0

其他说明

超级管理员用户名/密码:admin/123456。

数据库导入文件:/myweb/src/main/resources/SQL/myweb.sql
源码:

你可能感兴趣的文章
设计模式11_装饰器
查看>>
设计模式12_外观模式
查看>>
设计模式13_享元模式
查看>>
设计模式14_组合结构
查看>>
设计模式15_模板
查看>>
海龟交易法则01_玩风险的交易者
查看>>
CTA策略02_boll
查看>>
vnpy通过jqdatasdk初始化实时数据及历史数据下载
查看>>
设计模式19_状态
查看>>
设计模式20_观察者
查看>>
vnpy学习10_常见坑02
查看>>
用时三个月,终于把所有的Python库全部整理了!拿去别客气!
查看>>
pd.stats.ols.MovingOLS以及替代
查看>>
vnpy学习11_增加测试评估指标
查看>>
资金流入流出计算方法
查看>>
海龟交易法则07_如何衡量风险
查看>>
海龟交易法则08_风险与资金管理
查看>>
海龟交易法则09_海龟式积木
查看>>
海龟交易法则10_通用积木
查看>>
海龟交易法则14_掌控心魔
查看>>