该demo整合Shiro的相关配置参考开涛的博客

数据库表格相关设计

 
表格设计得比较简单,导航栏直接由角色表auth_role的角色描述vRoleDesc(父结点)和角色相关权限中的权限描述(标记为导航结点)vPermissionDesc(展开子项)组成。 

Shiro相关设置

密码输入错误次数限制

//密码重试5次次数限制
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher{
private Cache<String,AtomicInteger> passwordRetryCache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager){
passwordRetryCache=cacheManager.getCache("passwordRetryCache");
} @Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String username=(String)token.getPrincipal();
AtomicInteger retryCount=passwordRetryCache.get(username);
if(retryCount==null){
retryCount=new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if(retryCount.incrementAndGet()>5){
throw new ExcessiveAttemptsException();
}
boolean matches= super.doCredentialsMatch(token, info);//匹配密码
if(matches){
passwordRetryCache.remove(username);
}
return matches;
}
}

相关配置:

<!-- 凭证(密码)匹配器 -->
<bean id="credentialsMatcher" class="com.test.shiro.credentials.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<property name="hashAlgorithmName" value="md5"/><!--md5加密-->
<property name="hashIterations" value="2"/><!--加密迭代两次-->
<property name="storedCredentialsHexEncoded" value="true"/><!--为true时使用Hex编码(默认);false时使用Base64编码-->
</bean>

使用缓存实现为ehcache,相关配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="shiroCache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"<!--非永久有效-->
timeToIdleSeconds="3600"<!-- 对象空闲时间,即60min后失效-->
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<!--...-->
</ehcache>

扩展AuthorizingRealm:用于从数据库抓取密码等相关验证信息和相关权限信息

public class UserRealm extends AuthorizingRealm{

    @Autowired
private UserService userService; //获取相关授权信息
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName=(String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.findPermissionsByUserName(userName));//获取角色信息
authorizationInfo.setStringPermissions(userService.findPermissionsByUserName(userName));//获取权限信息 return authorizationInfo;
} //获取身份验证信息
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=(String)token.getPrincipal();
User user=userService.getUserByUserName(userName);//获取身份信息(密码和密码盐)
if(user==null){
throw new UnknownAccountException();
}
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
user.getUserName(),
user.getPassword(),
ByteSource.Util.bytes(user.getUserName()+user.getPasswordSalt()),
getName());
return authenticationInfo;
} }

登录相关

扩展FormAuthenticationFilter:用于登录后获取用户导航栏,并将其存入session范围

public class WithNavibarFormAuthenticationFilter extends FormAuthenticationFilter {

    @Autowired
private UserService userService; @Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
HttpServletRequest httpReq=(HttpServletRequest)request; String userName=(String)SecurityUtils.getSubject().getPrincipal();
List navigationBar=userService.getNavigationBar(userName);
httpReq.getSession().setAttribute("navibar", navigationBar);
return super.onLoginSuccess(token, subject, request, response);
} }

登录Controller实现(用户密码不匹配情况下执行)

@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
//... @RequestMapping("/login")
public ModelAndView login(HttpServletRequest req){
String error=null;
String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
ModelAndView mav=new ModelAndView("login");
mav.addObject("error", error);
return mav;
}
//...
}

登录表单代码:注意提交action=”“,以及输入控件name值须与form表单过滤器中的设置对应

<form class="form-signin" method="post" action="">
<h3 class="form-signin-heading">请登录</h3>
<label for="inputEmail" class="sr-only">用户名</label>
<input type="text" id="inputEmail" class="form-control" placeholder="用户名" name="username" required autofocus>
<label for="inputPassword" class="sr-only">密码</label>
<input type="password" id="inputPassword" class="form-control" placeholder="密码" name="password" required>
<div class="checkbox">
<label>
<input type="checkbox" name="rememberMe"> 记住我
</label>
</div>
<p class="bg-warning">${error}</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
</form>

最后通过Spring注解,控制访问

@RequiresPermissions("user:list")
@RequestMapping("/list")
public ModelAndView showUserList(){
//
}

完整shiro配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 缓存管理器 使用Ehcache实现 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:config/ehcache.xml"/>
</bean>
<!-- 凭证(密码)匹配器 -->
<bean id="credentialsMatcher" class="com.test.shiro.credentials.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="2"/>
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<!-- Realm实现 -->
<bean id="userRealm" class="com.test.shiro.realm.UserRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
<property name="cachingEnabled" value="true"/>
<property name="authenticationCachingEnabled" value="true"/>
<property name="authenticationCacheName" value="authenticationCache"/>
<property name="authorizationCachingEnabled" value="true"/>
<property name="authorizationCacheName" value="authorizationCache"/>
</bean>
<!-- 会话ID生成器 -->
<bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/> <!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="180000"/>
</bean> <!-- 会话DAO -->
<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
<property name="sessionIdGenerator" ref="sessionIdGenerator"/>
</bean> <!-- 会话验证调度器 -->
<bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
<property name="sessionValidationInterval" value="1800000"/>
<property name="sessionManager" ref="sessionManager"/>
</bean> <!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="1800000"/>
<property name="deleteInvalidSessions" value="true"/>
<property name="sessionValidationSchedulerEnabled" value="true"/>
<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
<property name="sessionDAO" ref="sessionDAO"/>
<property name="sessionIdCookieEnabled" value="true"/>
<property name="sessionIdCookie" ref="sessionIdCookie"/>
</bean> <!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="cacheManager" ref="cacheManager"/>
</bean> <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
<!-- 基于Form表单的身份验证过滤器 -->
<bean id="formAuthenticationFilter" class="com.test.shiro.filter.WithNavibarFormAuthenticationFilter">
<property name="usernameParam" value="username"/>
<property name="passwordParam" value="password"/>
<property name="rememberMeParam" value="rememberMe"/>
<property name="loginUrl" value="/user/login"/><!--注意value值为登录url-->
</bean>
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/user/login"/>
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/=authc
/index=authc
/user/login=authc<!-- 使用表单filter authc -->
/logout=logout
/static/**=anon<!-- 不拦截静态资源文件 -->
/**=user
</value>
</property>
</bean> <!-- Shiro生命周期处理器-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>

其他如dao、service、controller组件实现省略

完整代码见:https://github.com/weixupeng/auth-control_SSM

JavaWeb项目:Shiro实现简单的权限控制(整合SSM)的更多相关文章

  1. JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理

    1 学习计划 1.在realm中进行授权 2.使用shiro的方法注解方式权限控制 n 在spring文件中配置开启shiro注解支持 n 在Action方法上使用注解 3.★使用shiro的标签进行 ...

  2. Spring项目集成ShiroFilter简单实现权限管理

    Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证.授权.加密.会话管理.与Web集成.缓存等功能.我是从事javaweb工作的,我就经常遇到需要实现权限控制的项目,之前我们都是 ...

  3. elasticsearch使用jetty进行简单的权限控制

    默认elasticsearch是使用netty作为http的容器,由于netty并没有权限模块,所以默认es没有任何的权限控制,直接通过http就可以进行任何操作,除非把http禁用.但如果你使用el ...

  4. Shiro的认证和权限控制

    权限控制的方式 从类别上分,有两大类: - 认证:你是谁?–识别用户身份. - 授权:你能做什么?–限制用户使用的功能. 权限的控制级别 从控制级别(模型)上分: - URL级别-粗粒度 - 方法级别 ...

  5. shiro框架的四中权限控制方式

    https://www.cnblogs.com/cocosili/p/7103025.html 一.在自定义的realm中进行权限控制 在applicationContext.xml文件中添加  /a ...

  6. **CodeIgniter通过hook的方式实现简单的权限控制

    根据自己的实际情况,需要两个文件,一个是权限控制类,Acl,另外一个是权限配置的文件acl.php放在了config这个目录下. Acl这个类放在了application/hook/acl.php.通 ...

  7. springboot+mybatis+shiro——登录认证和权限控制

    转载:https://z77z.oschina.io/ 一.引入依赖 shiro-all包含shiro所有的包.shiro-core是核心包.shiro-web是与web整合.shiro-spring ...

  8. shiro框架学习-7- Shiro权限控制注解和编程方式

    讲解权限角色控制 @RequiresRoles, @RequiresPermissions等注解的使用和编程式控制 配置文件的方式 使用ShiroConfig 注解方式 @RequiresRoles( ...

  9. [PHP] 最简单的权限控制设计

    假设url部分我们只有action和method , 某个控制器下的某个方法 , 比如:log/loginlog   查看日志下的登陆日志, action就是log , method就是loginlo ...

随机推荐

  1. jquery 未来元素事件示例 on() delegate() live()

    jquery 1.7版后建议使用on() $(document).on("click","#green",function(){$(this).after('& ...

  2. CentOS7 配置阿里云yum源,非常之简单

    1.进入yum的文件夹 命令:cd   /etc/yum.repos.d/ 2.下载wget 命令:yum -y install wget 命令:yum install bash-completion ...

  3. ztree多种数据包装以及相关设置

    首先来一个完整的ztree代码 html代码 <form id="addTreeDataFrm" method="post" class="fo ...

  4. 【hiho1041】国庆出游 dfs+bitset

    题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,现遍历整棵树,要求每条边仅被经过两次,问是否存在一种特定的遍历方式使得 dfs 序中节点的相对前后关系符合给定的顺序. 题解: 首先,由于要 ...

  5. SSM框架中IoC、DI与AOP的理解

    框架封装了普通项目中程序员需要重复书写的代码和调用过程,就比如说在传统的jsp项目中,我们的controller接收到前端的请求然后程序员就需要去开发Dao层,里面还涉及数据库的连接和存储过程的代码, ...

  6. CentOS源码编译安装MySQL 5.5.15

    CentOS源码编译安装MySQL 5.5.15   文章目录 [隐藏] 安装编译工具 下载源码 安装cmake和bison 编译安装MySQL 一些相关设置 安装编译工具 yum install g ...

  7. return和exit以及C语言递归函数

    return 在主函数main()中,return整个函数退出,在子函数中return,只退出子函数. exit exit无论在函数什么位置退出整个函数 递归函数 #include <stdio ...

  8. autogen.sh 的使用

    在linux下面的大型工程很多都是makefile管理的,但是随着工程越来越大,makefile编写又成了一个大工程,这个时候出现了两个比较流行的工具,cmake和configure,configur ...

  9. 【java工具类】POI导出excel

    POI的maven依赖:<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi&l ...

  10. 【转载】自动化运维系列之Cobbler给Openstack节点安装操作系统

    preface 我们在一篇博文知道了如何搭建Cobbler,那么下面就通过Cobbler来安抓Openstack所有节点吧. 服务器配置信息如下: 主机名 IP 角色 Cobbler.node.com ...