您的位置:首页 > 其它

SSM集成Shiro安全框架(一)

2018-10-23 18:33 330 查看

一、目录结构

二、基础配置文件

1.pom.xml

[code]		<!-- 引入shiro框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<artifactId>ehcache-core</artifactId>
<groupId>net.sf.ehcache</groupId>
<version>2.5.0</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.3</version>
</dependency>

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>

<!-- Shiro 集成验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>

2.web.xml

[code]	<!-- 配置 Shiro 的 Filter -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

3.shiro.sql

[code]/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50537
Source Host           : localhost:3306
Source Database       : shiro

Target Server Type    : MYSQL
Target Server Version : 50537
File Encoding         : 65001

Date: 2018-09-03 10:12:43
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `permission`
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(8) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', 'addProduct');
INSERT INTO `permission` VALUES ('2', 'deleteProduct');
INSERT INTO `permission` VALUES ('3', 'editeProduct');
INSERT INTO `permission` VALUES ('4', 'updateProduct');
INSERT INTO `permission` VALUES ('5', 'listProduct');
INSERT INTO `permission` VALUES ('6', 'addOrder');
INSERT INTO `permission` VALUES ('7', 'deleteOrder');
INSERT INTO `permission` VALUES ('8', 'editeOrder');
INSERT INTO `permission` VALUES ('9', 'updateOrder');
INSERT INTO `permission` VALUES ('10', 'listOrder');

-- ----------------------------
-- Table structure for `role`
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(8) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'admin');
INSERT INTO `role` VALUES ('2', 'productManager');
INSERT INTO `role` VALUES ('3', 'orderManager');

-- ----------------------------
-- Table structure for `role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`rid` bigint(20) NOT NULL DEFAULT '0',
`pid` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`rid`,`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES ('1', '1');
INSERT INTO `role_permission` VALUES ('1', '2');
INSERT INTO `role_permission` VALUES ('1', '3');
INSERT INTO `role_permission` VALUES ('1', '4');
INSERT INTO `role_permission` VALUES ('1', '5');
INSERT INTO `role_permission` VALUES ('1', '6');
INSERT INTO `role_permission` VALUES ('1', '7');
INSERT INTO `role_permission` VALUES ('1', '8');
INSERT INTO `role_permission` VALUES ('1', '9');
INSERT INTO `role_permission` VALUES ('1', '10');
INSERT INTO `role_permission` VALUES ('2', '1');
INSERT INTO `role_permission` VALUES ('2', '2');
INSERT INTO `role_permission` VALUES ('2', '3');
INSERT INTO `role_permission` VALUES ('2', '4');
INSERT INTO `role_permission` VALUES ('2', '5');
INSERT INTO `role_permission` VALUES ('3', '6');
INSERT INTO `role_permission` VALUES ('3', '7');
INSERT INTO `role_permission` VALUES ('3', '8');
INSERT INTO `role_permission` VALUES ('3', '9');
INSERT INTO `role_permission` VALUES ('3', '10');

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(8) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`password` varchar(32) DEFAULT NULL,
`salt` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admin', '68609b8b64988c0f4def093eaa025e05', 'abcd');
INSERT INTO `user` VALUES ('2', 'li4', 'abcde', 'abcd');

-- ----------------------------
-- Table structure for `user_role`
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`uid` bigint(20) NOT NULL DEFAULT '0',
`rid` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`uid`,`rid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1');
INSERT INTO `user_role` VALUES ('1', '2');
INSERT INTO `user_role` VALUES ('2', '2');

三、权限控制demo

1.Spring配置文件(applicationContext.xml)中导入shiro配置文件:

[code]	<!-- 引入shiro的配置文件 -->
<import resource="classpath:applicationContext-shiro.xml" /> <!-- 7 -->

2.shiro配置文件applicationContext-shiro.xml

[code]<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">

<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/login.jsp" />
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址  -->
<property name="successUrl" value="/index.jsp" />
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<property name="filters">
<util:map>
<entry key="logout" value-ref="logoutFilter" />
</util:map>
</property>
<!-- 权限配置 -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何权限即可访问 -->
/login=anon
/kaptcha=anon
/kaptcha/get=anon
/icon/**=anon
/js/**=anon
/css/**=anon
<!--  -->/index.jsp = roles[admin]
<!--/index.jsp = roles["admin","productManager"] 要同时具有admin,productManager两个角色权限 -->
<!--/index.jsp = roleOrFilter["admin","productManager"] 只需具有其中一个权限就可以,但需要自定义filter -->
/logout=logout
<!-- 所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->
/** = authc

</value>
</property>
</bean>

<!-- 退出登陆配置 -->
<bean id="logoutFilter"
class="org.apache.shiro.web.filter.authc.LogoutFilter">
<!-- 重定向退出登陆的地址 -->
<property name="redirectUrl" value="logout.jsp" />
</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="-1" />
</bean>
<!-- 会话DAO -->
<bean id="sessionDAO"
class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="sessionIdGenerator" ref="sessionIdGenerator" />
</bean>
<!-- 会话验证调度器,每30分钟执行一次验证 ,设定会话超时及保存 -->
<bean name="sessionValidationScheduler"
class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
<property name="interval" value="1800000" />
<property name="sessionManager" ref="sessionManager" />
</bean>
<!-- 会话管理器 -->
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 全局会话超时时间(单位毫秒),默认30分钟 -->
<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" /> <!-- 1 -->
<!-- 使用下面配置的缓存管理器 -->
<property name="cacheManager" ref="cacheManager" />
<property name="sessionManager" ref="sessionManager" />
</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>

<!-- 注册自定义的Realm,并把密码匹配器注入,使用注解的方式自动注解会无法正确匹配密码 -->
<bean id="userRealm" class="com.yan.shiro.common.UserRealm"><!-- 2 -->
<!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>

<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property> <!-- 加密算法的名称 -->
<property name="hashIterations" value="1024"></property> <!-- 配置加密的次数 -->
</bean>
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> </bean>

<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">/403</prop>
</props>
</property>
</bean>
</beans>

3.定义shiro拦截器(UserRealm.java)

[code]package com.yan.shiro.common;

import java.util.Set;

import org.apache.shiro.SecurityUtils;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
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 com.yan.shiro.model.User;
import com.yan.shiro.service.UserService;

public class UserRealm extends AuthorizingRealm {

@Autowired
private UserService userService;

/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("UserRealm的doGetAuthorizationInfo方法开始执行");
//获取当前登陆的用户名
String username=(String)principals.getPrimaryPrincipal();
System.out.println("username:"+username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//从数据库中查找该用户名拥有的角色
Set<String> roleList = userService.selectRoleByUserName(username);
// 添加角色
authorizationInfo.addRoles(roleList);
// 添加权限
// authorizationInfo.setStringPermissions(userService.findPermissions(username));
return authorizationInfo;
}

/**
* 登陆验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("UserRealm的doGetAuthenticationInfo方法开始执行");
//获取当前登陆的用户名
String userName = (String) token.getPrincipal();
//从数据库中获取user
User user = userService.selectByUserName(userName);
// 为密码加盐
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());// 这里的参数要给个唯一的;
// 校验
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getName(), user.getPassword(),credentialsSalt, getName());
return authenticationInfo;
}

public static void main(String[] args) {
SimpleHash MD5 = new SimpleHash("MD5", "123456", ByteSource.Util.bytes("小明"), 1024);
System.out.println(MD5);
}
}

4.UserController.java

[code]	@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(HttpServletRequest request) {
System.out.println("UserController的login方法开始执行");
String username = request.getParameter("username");
String password = request.getParameter("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
//执行认证操作.
subject.login(token);
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return "success";
}

四、JSP标签

1.导入标签库

[code]<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

2.guest标签

[code]<shiro:guest>
欢迎游客访问,<a href="${pageContext.request.contextPath}/login.jsp">登录</a>
</shiro:guest>

3.user 标签

[code]<shiro:user>
欢迎 用户访问,<a href="${pageContext.request.contextPath}/login.jsp">登录</a>
</shiro:user>

4.principal 标签

[code]<!-- 显示用户身份信息,默认调用 Subject.getPrincipal() 获取-->
<shiro:principal type="java.lang.String"/><!-- 相当于 Subject.getPrincipals().oneByType(String.class)  -->

<shiro:principal type="java.lang.String"/> <!-- 相当于 Subject.getPrincipals().oneByType(String.class) -->

5.lacksRole 标签

[code]<shiro:lacksRole name="abc">
用户[<shiro:principal/>]没有角色abc<br/> <!-- 如果当前 Subject abc角色将显示 body 体内容。 -->
</shiro:lacksRole>

6.hasPermission 标签

[code]<shiro:hasPermission name="user:create">
用户[<shiro:principal/>]拥有权限user:create<br/> <!-- 如果当前 Subject 有create权限将显示 body 体内容。 -->
</shiro:hasPermission>

7.lacksPermission 标签

[code]<shiro:lacksPermission name="org:create">
用户[<shiro:principal/>]没有权限org:create<br/> <!-- 如果当前 Subject 没有create权限将显示 body 体内容。  -->
</shiro:lacksPermission>

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: