SSM+shiro实现角色授权认证管理

一、pom.xml添加依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>sdm.cn</groupId>
  <artifactId>sdm-web</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
    <dependencies>
		<!-- spring-webmvc依赖jar包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.9.RELEASE</version>
		</dependency>
		
		<!-- spring-jdbc依赖jar包 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.3.9.RELEASE</version>
		</dependency>
		
		<!-- mybatis依赖jar包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.8</version>
		</dependency>
		
		<!-- mybatis-spring依赖jar包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.3.2</version>
		</dependency>
		
		<!-- mysql依赖jar包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
		</dependency>
		
		<!-- commons-dbcp依赖jar包 -->
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>
		
		<!-- junit依赖jar包 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		
		<!-- jstl依赖jar包 -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		
		<!-- shiro依赖 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>1.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.2.1</version>
		</dependency>
	</dependencies>
</project>
二、web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>sdm-web</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <!-- 
  		1.指定spring的配置文件有两种
  			application-*.xml,spring-shiro.xml
  		2.指定springmvc的配置文件
  			spring-mvc.xml
  		3.使用shiro过滤器
  			DelegatingFilterProxy
   -->
   
   
  	<!-- 配置上下文的初始化参数 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:application-*.xml,
			classpath:spring-shiro.xml
		</param-value>
	</context-param>
	<!-- 配置上下文监听器,度上下文的初始化参数 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- 配置过滤器,设置post请求编码格式 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<!-- 设置初始化参数 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<!-- 配置前端控制器 -->
	<servlet>
		<servlet-name>dispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	
	<!-- Shiro配置 -->
    <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>
    </filter-mapping>
</web-app>
三、spring-shiro.xml
<?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="/user/showLogin.do" />
		<!-- 配置登录验证成功后的请求地址 -->
		<property name="successUrl" value="/dormitory/showIndex.do" />
		<!-- 如果请求的资源不再该角色的权限范围,跳转的请求地址 -->
		<property name="unauthorizedUrl" value="/unauthorized" />
		<!-- 退出 -->
		<property name="filters">
			<util:map>
				<entry key="logout" value-ref="logoutFilter" />
			</util:map>
		</property>
		<!-- 权限配置 -->
		<property name="filterChainDefinitions">
			<value>
				<!-- anon表示该地址不需要任何权限,即可访问 -->
				/css/**=anon
				/images/**=anon
				/js/**=anon
				/user/showLogin.do=anon
				/user/login.do=anon
				<!-- 请求 logout.action地址,shiro去清除session -->
                /user/exit.do = logout
				<!--所有的请求(除去配置的静态资源请求、请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/user/showLogin.do -->
				/** = authc
			</value>
		</property>
	</bean>
	<!-- 退出过滤器 -->
	<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
		<property name="redirectUrl" value="/user/showLogin.do" />
	</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="myUserRealm" />
		<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>

	<bean id="myUserRealm" class="cn.sdm.shiro.MyUserRealm">
	</bean>

	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
四、Controller 添加异步提交登录请求方法
// 异步提交登录
@RequestMapping("/login.do")
@ResponseBody
public ResponseResult<Void> login(String username, String password, String inputCaptcha){
   // 获取当前应用交互主体
   Subject subject = SecurityUtils.getSubject(); 
   Session session=subject.getSession();
   ResponseResult<Void> rr = null;
   // UsernamePasswordToken用来存储用户和密码
   UsernamePasswordToken token = new UsernamePasswordToken(username, password);
   try { 
      // 跳转到认证
      subject.login(token);
      rr = new ResponseResult<Void>(1,"登录成功");
      System.out.println("登录成功");
   } catch (AuthenticationException e) { 
      rr = new ResponseResult<Void>(0,"用户名或密码错误");
      System.out.println("登录失败: "+e.getMessage());
   }
        
   return rr;
}
五、MyUserRealm
package cn.shiro;
 
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import cn.bean.User;
import cn.mapper.UserMapper;
import cn.service.UserService;
import cn.service.ex.PasswordNotMatchException;

/**
 * shiro安全权限管理
 * @author 
 *
 */
public class MyUserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private UserMapper userMapper;
//    // 加盐
//     @Value("#{config.salt}")
//     private String salt;

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //账号已通过验证
        String username =(String) principalCollection.getPrimaryPrincipal();
        System.out.println("username:"+username);
        //通过service获取角色和权限
        List<Map<String,Object>> permissionsList = userService.selectPermissionsByUsername(username);
        Set<String> permissions = new HashSet<String>();
        for(Map<String,Object> map : permissionsList){
           permissions.add(ObjectUtils.toString(map.get("permissionCode")));
        }
        List<Map<String,Object>> rolesList = userService.selectRolesByUsername(username);
        Set<String> roles = new HashSet<String>();
        for(Map<String,Object> map : rolesList){
           roles.add(ObjectUtils.toString(map.get("roleName")));
        }
        System.out.println("roles: "+roles.toString());
        //授权对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //把通过service获取到的角色和权限放进去
        info.setStringPermissions(permissions);
        info.setRoles(roles);
        return info;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取账号密码
        UsernamePasswordToken t = (UsernamePasswordToken) token;
        String username= token.getPrincipal().toString();
        String password= new String(t.getPassword());
        // 获取数据库中的密码
        User user = userMapper.selectByUsername(username);
        String passwordInDB = user.getPassword();
//        // 如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不是抛出具体错误原因,免得给破解者提供帮助信息
//        if(null==passwordInDB || !passwordInDB.equals(password)){
//         throw new AuthenticationException();
//        }
        // 认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :myUserRealm
//        // 获取盐,用于对密码在加密算法(MD5)的基础上二次加密
//        ByteSource byteSalt = ByteSource.Util.bytes(salt);?
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,passwordInDB,this.getName());
        Session session=SecurityUtils.getSubject().getSession();
        session.setAttribute("user", user);
        return info;
    }
 
}
六、前端部分
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
<%@ taglib prefix="shiroextend" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html>
<html>
<head lang="en">
   <meta charset="utf-8" />
   <title>XXX管理平台</title>
   <script src="../js/jquery-3.1.1.min.js"></script>
   <script src="../js/jquery.cookie.js"></script>
 <script type="text/javascript">
 </script>
</head>

<body>
   <div class="left-container"> 
      <ul class="left-menu" onclick="">
         <li class="big-menu" id="">
            <img class="icon1" src="../images/icon/dormitory.png"/>
            <a href="#" class="menu1">宿舍管理<img class="icon2" src="../images/icon/tobottom.png"/></a>
            <ul class="small-menu">
               <li class="menu2" id="" onclick="">
                  <a href="../dormitory/showIndex.do">&nbsp;&nbsp;宿舍查看</a>
               </li>
               <!-- 使用shiro标签 -->
               <%-- <shiro:hasRole name="管理员"> --%>
               <shiro:hasPermission name="dormitory_manage">
               <li class="menu2" id="" onclick="">
                  <a href="../dormitory/dormitoryManage.do">&nbsp;&nbsp;宿舍调整</a>
               </li>
               </shiro:hasPermission>
               <%-- </shiro:hasRole> --%>
            </ul>
         </li>

         <shiroextend:hasAnyPermissions name="dormitory_cost,apartment_cost">
            <li class="big-menu" id="">
               <img class="icon1" src="../images/icon/cost.png"/>
               <a href="#" class="menu1">费用管理<img class="icon2" src="../images/icon/tobottom.png"/></a>
               <ul class="small-menu">
                  <shiro:hasPermission name="dormitory_cost">
                     <li class="menu2" id="" onclick="">
                        <a href="../cost/dormitoryCost.do">&nbsp;&nbsp;宿舍费用</a>
                     </li>
                  </shiro:hasPermission>
                  <shiro:hasPermission name="apartment_cost">
                     <li class="menu2" id="" onclick="">
                        <a href="../cost/apartmentCost.do">&nbsp;&nbsp;公寓物品费用</a>
                     </li>
                  </shiro:hasPermission>
               </ul>
            </li>
         </shiroextend:hasAnyPermissions>
         
         <shiroextend:hasAnyPermissions name="role_manage,account_manage">
         <li class="big-menu" id="">
            <img class="icon1" src="../images/icon/user.png"/>
            <a href="#" class="menu1">用户管理<img class="icon2" src="../images/icon/tobottom.png"/></a>
            <ul class="small-menu">
               <shiro:hasPermission name="role_manage">
               <li class="menu2" id="" onclick="">
                  <a href="../user/roleManage.do">&nbsp;&nbsp;角色管理</a>
               </li>
               </shiro:hasPermission>
               <shiro:hasPermission name="account_manage">
               <li class="menu2" id="" onclick="">
                  <a href="../user/accountManage.do">&nbsp;&nbsp;账号管理</a>
               </li>
               </shiro:hasPermission>
            </ul>
         </li>
         </shiroextend:hasAnyPermissions>
      </ul>
   </div>
   
   <!-- 引用修改密码模态框 -->
   <%@ include file="update_password.jsp" %>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/awen6666/article/details/104546964
今日推荐