shiro是一个易用的权限管理框架,只需提供一个Realm即可在项目中使用,本文就将结合上一篇中搭建的权限模块、角色模块和用户模块来搭建一个粗粒度的权限管理系统,具体如下:
1. 添加shiro依赖和与thymeleaf集成的依赖,并更新项目:

 <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>1.0.2</version>
</dependency>

pom.xml

2. 添加自定义Realm类,主要完成用户校验和授权的功能

 package com.lvniao.blog.config;

 import java.util.HashSet;
import java.util.Set; import javax.annotation.Resource; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import com.lvniao.blog.mapper.UserMapper;
import com.lvniao.blog.model.User; @Component
public class ShiroRealm extends AuthorizingRealm { @Autowired
private UserMapper userMapper; protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String)principals.getPrimaryPrincipal();
User user = userMapper.getUserWithRoleByName(username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
user.getRolesAndPermissions(roles, permissions);
authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
} protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;
String username = (String)usernamePasswordToken.getPrincipal();
String password = new String(usernamePasswordToken.getPassword());
if(userMapper.check(username, password) != null) {
User user = userMapper.getUserByName(username); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getName(),
user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); return authenticationInfo;
} else {
throw new AuthenticationException();
}
}
}

ShiroRealm

3. 添加ShiroConfiguration类,完成shiro的配置

 package com.lvniao.blog.config;

 import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager; @Configuration
public class ShiroConfiguration{ @Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/admin/login"); shiroFilterFactoryBean.setSuccessUrl("/admin/"); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/admin/loginaction", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
System.out.println("Shiro拦截器工厂类注入成功");
return shiroFilterFactoryBean;
} @Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(ShiroRealm());
return securityManager;
} @Bean
public ShiroRealm ShiroRealm() {
ShiroRealm shiroRealm = new ShiroRealm();
return shiroRealm;
} @Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}

ShiroConfiguration

因为添加了filterChainDefinitionMap.put("/**", "authc"),所以shiro会对所有请求进行验证,包括静态资源,所以需要通过如: filterChainDefinitionMap.put("/css/**", "anon");这样的来使静态资源请求不被拦截。通过这三个步骤就已经把shiro配置好了,下面就完成登录部分:
4. 添加登录action

 package com.lvniao.blog.admin.controller;

 import java.util.List;

 import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import com.lvniao.blog.mapper.MenuMapper;
import com.lvniao.blog.mapper.UserMapper;
import com.lvniao.blog.model.Menu;
import com.lvniao.blog.model.User;
import com.lvniao.blog.util.Constant; @Controller
@RequestMapping("/admin")
public class AdminController { @Autowired
private UserMapper userMapper; @Autowired
private MenuMapper menuMapper; @RequestMapping("/")
public String index(Model model) {
model.addAttribute("menus", menuMapper.getParentMenu());
return "admin/index";
} @RequestMapping("/menu")
public String menu(Model model) {
return "admin/menu1";
} @RequestMapping("/login")
public String login() {
return "admin/login";
} @RequestMapping("/loginaction")
public ModelAndView loginAction(User user) {
Subject subject = SecurityUtils.getSubject();
if(!subject.isAuthenticated()) { try {
User u = userMapper.getUserByName(user.getName());
if(u != null) {
String password = new Md5Hash(user.getPassword(), u.getSalt()).toString();
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), password);
token.setRememberMe(false);
subject.login(token);
User currentUser = userMapper.getUserByName(user.getName());
subject.getSession().setAttribute(Constant.CurrentUser, currentUser);
return new ModelAndView("redirect:/admin/");
} } catch(UnknownAccountException ex) { } catch (IncorrectCredentialsException ex) { } catch (Exception ex) { }
}
return new ModelAndView("redirect:/admin/login");
}
}

AdminController

5. 添加登录页

 <!DOCTYPE HTML>
<html>
<head>
<title>lvniao</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" th:href="@{/css/base.css}"/>
<link rel="stylesheet" th:href="@{/css/font-awesome.css}"/>
<link rel="stylesheet" th:href="@{/css/login.css}"/>
<script th:src="@{/js/jquery-3.2.1.js}"></script>
<script th:src="@{/statics/js/base.js}"></script>
<style>
*{
margin:0px;
padding:0px;
}
body{
background-image:url("/images/loginbg.jpg") ;
background-size:100% 100%;
}
</style>
</head>
<body>
<form class="login" th:action="@{/admin/loginaction}" th:method="post">
<div class="header">
<h1>登录</h1>
</div>
<div class="text name">
<input type="text" class="input" name="name" placeholder="用户名"/>
</div>
<div class="text password">
<input type="password" class="input" name="password" placeholder="密码"/>
</div>
<button type="submit" class="button">登录</button>
<div class="foot">
</div>
</form>
</body>
</html>

login.html

其中在css中使用url可以按照正常的使用,不用按照html中添加资源的方式。

登录成功后就会跳转到/admin/页

6. 因为在上一篇文章中以及添加好了角色授权和给用户赋角色,而现在要做的就是使用shiro来对界面做粗粒度权限管理,shiro在验证授权时需要获得用户的角色列表和权限列表,所以首先就修改User.java,增加获取角色和权限的接口,代码如下:

 package com.lvniao.blog.model;

 import java.util.ArrayList;
import java.util.List;
import java.util.Set; import com.lvniao.blog.model.Permission;
import com.lvniao.blog.model.Role;
import com.lvniao.blog.util.StringUtil; public class User { private Long id; private String name; private String password; private String salt; private Boolean locked; private List<Role> roles = new ArrayList<Role>(); private String rolesStr = null; 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 getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getSalt() {
return salt;
} public void setSalt(String salt) {
this.salt = salt;
} public Boolean isLocked() {
return locked;
} public void setLocked(Boolean locked) {
this.locked = locked;
} public List<Role> getRoles() {
return roles;
} public void setRoles(List<Role> roles) {
this.roles = roles;
} public String getRolesStr() {
if(StringUtil.isNullOrEmpty(rolesStr)) {
if(getRoles() != null && getRoles().size() > 0) {
StringBuffer sb = new StringBuffer(); for(Role r : getRoles()) {
if(r != null) {
sb.append(r.getId());
sb.append(",");
}
}
if(sb.length() > 0) {
rolesStr = sb.toString().substring(0, sb.length() - 1);
}
}
}
return rolesStr;
} public void setRolesStr(String rolesStr) {
this.rolesStr = rolesStr;
} public void getRolesAndPermissions(Set<String> roleres, Set<String> permissionres) {
getRolesAndPermissions(getRoles(), roleres, permissionres);
} private void getRolesAndPermissions(List<Role> roles, Set<String> roleres, Set<String> permissionres) {
for(Role role : roles) {
roleres.add(role.getAlias());
for(Permission p : role.getPermissions()) {
permissionres.add(p.getAlias());
}
getRolesAndPermissions(role.getChildren(), roleres, permissionres);
}
}
}

User.java

使用时通过getRolesAndPermissions方法获得用户的角色集合和权限集合,已经在ShiroRealm中添加好了。然后就是在页面上使用权限管理;
7. 这儿以不同角色用户登录后,在用户管理界面上展示对操作权限的限制为例,用户管理界面的代码如下:

 <!DOCTYPE html>
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8"/>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" th:href="@{/css/page.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/easyui/themes/default/easyui.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/easyui/themes/icon.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/layui/css/layui.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/css/grid.css}"/>
<script type="text/javascript" th:src="@{/easyui/jquery.min.js}"></script>
<script type="text/javascript" th:src="@{/easyui/jquery.easyui.min.js}"></script>
<script type="text/javascript" th:src="@{/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/layui/layui.all.js}"></script>
<script type="text/javascript" th:src="@{/js/form.js}"></script>
<script>
$(function(){
$("#grid").treegrid({url: '/user/list',
method: 'get',
rownumbers: true,
idField: 'id',
fit:true,
treeField: 'name',
pagination: true,
pageSize: 10,
pageList: [10, 50, 100]});
$("#btnSearch").click(function(){
$("#grid").treegrid({queryParams:form2Json("query")});
}); $(".lv-btn-group .lv-btn").click(function(){
var type = $(this).attr("type");
var addr = $(this).attr("addr");
if(type == "refresh"){
$(".lv-txtSearch").val("");
$("#grid").treegrid({queryParams:form2Json("query")});
return;
}
if(type == "add"){
layer.open({
type: 2,
title: $(this).attr("title"),
shadeClose: true,
shade: 0.8,
area: ['330px', '270px'],
content: addr,
success:function(layero){
$("#grid").treegrid({queryParams:form2Json("query")});
}
});
return;
} var row = $("#grid").treegrid("getSelected");
if(row == null){
layer.alert("请选择待操作的数据");
return;
}
if(type == "assign"){
layer.open({
type: 2,
title: $(this).attr("title"),
shadeClose: true,
shade: 0.8,
area: ['330px', '300px'],
content: addr + "/" + row.id,
success:function(layero){
$("#grid").treegrid({queryParams:form2Json("query")});
}
});
return;
}
if(type == "modify"){
layer.open({
type: 2,
title: $(this).attr("title"),
shadeClose: true,
shade: 0.8,
area: ['330px', '270px'],
content: addr + "/" + row.id,
success:function(layero){
$("#grid").treegrid({queryParams:form2Json("query")});
}
});
return;
}
if(type == "delete"){
$.ajax({
url:addr + "/" + row.id,
type:"get",
success:function(data){
$("#grid").treegrid({queryParams:form2Json("query")});
}
});
return;
} });
});
</script>
</head>
<body>
<div class="lv-option-container">
<form id="query" shiro:hasPermission="user:query" >
<input type="text" class="lv-txtSearch" name="query"/><div class="lv-btnSearch" id="btnSearch">查询</div>
</form> <div class="lv-btn-group">
<div class="lv-btn" type="refresh" shiro:hasPermission="user:refresh">刷新</div>
<div class="lv-btn" type="add" addr="/user/add" shiro:hasPermission="user:add" title="添加">添加</div>
<div class="lv-btn" type="modify" addr="/user/modify" shiro:hasPermission="user:modify" title="修改">修改</div>
<div class="lv-btn" type="assign" addr="/user/assign" shiro:hasPermission="user:assign" style="width:100px;" title="删除">分配角色</div>
<div class="lv-btn" type="delete" addr="/user/delete" shiro:hasPermission="user:delete" title="删除">删除</div>
</div>
</div>
<div class="lv-grid-container">
<table id="grid">
<thead>
<tr>
<th data-options="field:'name'" width="220">用户名</th>
<th data-options="field:'locked', formatter:booleanFormat" width="220">是否锁定</th>
</tr>
</thead>
</table>
</div>
</body>
</html>

index.html

首先要在HTML标记中添加<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">,然后在需要控制权限的界面元素上通过shiro:hasPermission="xxx"来验证当前用户是否有权限操作该元素,如上就完成了粗粒度的权限管理,下面是分别有所有权限和只有查询和刷新权限的界面:

代码下载路径:https://pan.baidu.com/s/1VqcDk9BIM10-HVyfmrjMHg, 密码:vxtg

7. 整合shiro,搭建粗粒度权限管理的更多相关文章

  1. Shiro 整合SpringMVC 并实现权限管理,登录和注销

    Shiro 整合SpringMVC 并且实现权限管理,登录和注销 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring S ...

  2. Shiro系列(0) - 权限管理在J2EE企业级开发中的应用与实战

    其实也是应大家要求,讲一下权限管理,之前有讲过,但是没有拿出来细讲,这次索性录了视频从头到尾把shiro讲一遍.后续spring security会另外找个时间也讲一下. 主要内容会包括以下 1.了解 ...

  3. shiro实现动态权限管理

    用到shiro框架实现权限控制时,根据实际要求,权限在数据库增删改后都要把权限过滤链变化实时更新到服务器中. 1.配置文件里配置的filterchains都是静态的,但实际开发中更多的是从数据库中动态 ...

  4. springBoot整合spring security实现权限管理(单体应用版)--筑基初期

    写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...

  5. Shiro系列(1) - 权限管理的介绍与原理

    1. 什么是权限管理 一般来说,只要有用户参与,那么该系统都会需要权限管理,权限管理实现了对用户访问系统  指定功能的限制,按照管理员定义的安全规则或权限策略,限制用户只能访问自己被授权的那些资源路径 ...

  6. Shiro 整合SpringMVC 并且实现权限管理

    Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大 ...

  7. Shiro 整合SpringMVC 并且实现权限管理,登录和注销

    Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大 ...

  8. SpringBoot 整合Shiro实现动态权限加载更新+Session共享+单点登录

    作者:Sans_ juejin.im/post/5d087d605188256de9779e64 一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shir ...

  9. JavaWeb之ssm框架整合,用户角色权限管理

    SSM框架整合 Spring SpringMVC MyBatis 导包: 1, spring 2, MyBatis 3, mybatis-spring 4, fastjson 5, aspectwea ...

随机推荐

  1. ActiveMQ 入门

    1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ 2.运行ActiveMQ 解压缩apache-activemq-5.5.1-bin.zip,然后双击a ...

  2. git push 小结

    $ git push ssh://git@dev.lemote.com/rt4ls.git master // 把本地仓库提交到远程仓库的master分支中 $ git remote add orig ...

  3. javascript加RoR实现JSONP

    我们知道不同域中的js代码受同源策略的限制,不同域中的AJAX同样受此限制,不过使用html中的script远程脚本可以跳过该限制,下面我们实际看一下利用RoR和js如何实现所谓的JSONP. 这里只 ...

  4. 类似Jquery ui 标签页(Tabs)

    <div class="indexnew_tit"> <a href="javascript:;" class="on"& ...

  5. Day6_time模块

    TIME模块: print(time.time()) #指的是从1970年到现在的秒数 print(time.strftime('%Y-%m-%d %X'))  #指定特定的格式输出时间 print( ...

  6. geth常用指令

    ubuntu下载: https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Ubuntu sudo apt ...

  7. 从前端开发看HTTP协议的应用

    一.Chrome Developer Network Tab Cheome Developer作为现在前端开发者最常用的开发调试工具,其具有前端可以涉及到的各方面的强大功能,为我们的开发和定位问题提供 ...

  8. Django升级1.9.6出现的中文本地化bug

    Error日志: Error opening file for reading: Permission denied ERROR Internal Server Error: / Traceback  ...

  9. C#避免踩坑之如何添加paint事件

    看截图: 首先,右击->属性 然后出来这个界面. 接下来,注意看这个界面的上面:鼠标悬停这个闪电符号,看到没,事件!! 那个闪电符号,点它! 然后下拉找到这个: 你要事先在代码里面添加Form1 ...

  10. birt4.6部署到tomcat及启动服务报错解决方法

    一.下载birt-runtime-4.6.0-20160607.zip包 解压后birt-runtime-4.6.0-20160607\WebViewerExample将WebViewerExampl ...