shiro授权

ShiroUserMapper
    Set<String> getRolesByUserId(Integer uid);

    Set<String> getPersByUserId(Integer uid);
ShiroUserMapper.xml
 <select id="getRolesByUserId" resultType="java.lang.String" parameterType="java.lang.Integer">
    select r.roleid from t_shiro_user u,t_shiro_user_role ur,t_shiro_role r
      where u.userid = ur.userid and ur.roleid = r.roleid
      and u.userid = #{uid}
  </select>
  <select id="getPersByUserId" resultType="java.lang.String" parameterType="java.lang.Integer">
    select p.permission from t_shiro_user u,t_shiro_user_role ur,t_shiro_role_permission rp,t_shiro_permission p
    where u.userid = ur.userid and ur.roleid = rp.roleid and rp.perid = p.perid
    and u.userid = #{uid}
  </select>
ShiroUserService
package com.wsy.service;

        import com.wsy.model.ShiroUser;

        import java.util.Set;

/**
 * @author干的漂亮
 * @site www.wangmage.com
 * @company 干得漂亮公司
 * @create 2019 - 10-13 21:50
 */
public interface ShiroUserService {
    /**
     * 用于shiro认证
     * @param uname
     * @return
     */
    public ShiroUser queryByName(String uname);

    int insert(ShiroUser shiroUser);

    Set<String> getRolesByUserId(Integer uid);

    Set<String> getPersByUserId(Integer uid);
}

ShiroUserServiceImpl
package com.wsy.service.impl;

        import com.wsy.mapper.ShiroUserMapper;
        import com.wsy.model.ShiroUser;
        import com.wsy.service.ShiroUserService;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;

        import java.util.Set;

/**
 * @author干的漂亮
 * @site www.wangmage.com
 * @company 干得漂亮公司
 * @create 2019 - 10-13 21:52
 */
@Service("shiroUserService")
public class ShiroUserServiceImpl implements ShiroUserService {
    @Autowired
    private ShiroUserMapper shiroUserMapper;
    @Override
    public ShiroUser queryByName(String uname) {
        return shiroUserMapper.queryByName(uname);
    }

    @Override
    public int insert(ShiroUser shiroUser) {
        return shiroUserMapper.insert(shiroUser);
    }

    @Override
    public Set<String> getRolesByUserId(Integer uid) {
        return shiroUserMapper.getRolesByUserId(uid);
    }

    @Override
    public Set<String> getPersByUserId(Integer uid) {
        return shiroUserMapper.getPersByUserId(uid);
    }
}

MyRealm 测试

    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        ShiroUser shiroUser = this.shiroUserService.queryByName(principals.getPrimaryPrincipal().toString());
        Set<String> roleids = this.shiroUserService.getRolesByUserId(shiroUser.getUserid());
        Set<String> perIds = this.shiroUserService.getPersByUserId(shiroUser.getUserid());

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roleids);
        info.setStringPermissions(perIds);
        return info;
    }

权限分为五个表
Shiro授权-SSM_xml

注解式开发
常用注解介绍
  @RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subject.isAuthenticated()返回 true
  @RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
  @RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
  @RequiresRoles(value = {"admin","user"},logical = Logical.AND):表示当前Subject需要角色admin和user
  @RequiresPermissions(value = {"user:delete","user:b"},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b
ShiroUserController
package com.wsy.controller;

import com.wsy.model.ShiroUser;
import com.wsy.service.ShiroUserService;
import com.wsy.util.PasswordHelper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author干的漂亮
 * @site www.wangmage.com
 * @company 干得漂亮公司
 * @create 2019 - 10-14 16:20
 */
@Controller
public class ShiroUserController {
    @Autowired
    private ShiroUserService shiroUserService;
    @RequestMapping("/login")
    public String login(HttpServletRequest req, HttpServletResponse resp){
        Subject subject = SecurityUtils.getSubject();
        String uname = req.getParameter("username");
        String pwd = req.getParameter("password");
        UsernamePasswordToken token = new UsernamePasswordToken(uname,pwd);
        try {
            subject.login(token);
            return "main";
        }catch (Exception e){
            req.setAttribute("message","用户名或密码错误~~~");
            return "login";
        }
    }
    @RequestMapping("/logout")
    public String logout(HttpServletRequest req, HttpServletResponse resp){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
    /**
     * 把加密后的密码存入数据库中
     * @param req
     * @param resp
     * @return
     */
    @RequestMapping("/register")
    public String register(HttpServletRequest req, HttpServletResponse resp){
        String uname = req.getParameter("username");
        String pwd = req.getParameter("password");
        String salt = PasswordHelper.createSalt();
        String credentials = PasswordHelper.createCredentials(pwd, salt);

        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setUsername(uname);
        shiroUser.setPassword(credentials);
        shiroUser.setSalt(salt);
        int n = shiroUserService.insert(shiroUser);
        if(n > 0){
            req.setAttribute("message","注册成功");
            return "login";
        }
        else{
            req.setAttribute("message","注册失败");
            return "login";
        }
    }

    /**
     * 讲解身份认证的注解
     * @param req
     * @param resp
     * @return
     */
    @RequiresUser
    @RequestMapping("/passUser")
    public String passUser(HttpServletRequest req,HttpServletResponse resp){
        return "admin/addUser";
    }

    /**
     * 角色认证
     * @param req
     * @param resp
     * @return
     * 当前方法必须同时具备1、4的角色id,才能够被访问
     */
    @RequiresRoles(value = {"1","4"},logical = Logical.AND)
    @RequestMapping("/passRole")
    public String passRole(HttpServletRequest req,HttpServletResponse resp){
        return "admin/listUser";
    }

    /**
     * 权限认证
     * @param req
     * @param resp
     * @return
     */
    @RequiresPermissions(value = {"user:update","user:view"},logical = Logical.OR)
    @RequestMapping("/passPer")
    public String passPer(HttpServletRequest req,HttpServletResponse resp){
        return "admin/resetPwd";
    }

    /**
     * 如果身份、角色、权限认证失败后的处理方式
     * @param req
     * @param resp
     * @return
     */
    @RequestMapping("/unauthorized")
    public String unauthorized(HttpServletRequest req,HttpServletResponse resp){
        System.out.println("错误认证处理方案!!!");
        return "unauthorized";
    }

}

需要在springMVC中使用shiro注解,所以需要把我们的securityManager安全管理器和我们的错误信息处理交给springMVC来管,所以就需要把它们配置进入spring-MVC.xml中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.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.xsd">
    <!-- 通过context:component-scan元素扫描指定包下的控制器-->
    <!--1) 扫描com.javaxl.zf及子子孙孙包下的控制器(扫描范围过大,耗时)-->
    <aop:aspectj-autoproxy/>
    <context:component-scan base-package="com.wsy"/>

    <!--2) 此标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
    <!--两个bean,这两个bean是spring MVC为@Controllers分发请求所必须的。并提供了数据绑定支持,-->
    <!--@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!--3) ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- viewClass需要在pom中引入两个包:standard.jar and jstl.jar -->
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 文件最大大小(字节) 1024*1024*50=50M-->
        <property name="maxUploadSize" value="52428800"></property>
        <!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常-->
        <property name="resolveLazily" value="true"/>
    </bean>

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"></property>
    </bean>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthorizedException">
                    unauthorized
                </prop>
            </props>
        </property>
        <property name="defaultErrorView" value="unauthorized"/>
    </bean>


    <!--4) 单独处理图片、样式、js等资源 -->
    <!--<mvc:resources location="/css/" mapping="/css/**"/>-->
    <mvc:resources location="/statis/" mapping="/statis/**"/>
   <!--<mvc:resources location="/js/" mapping="/js/**"/>-->


</beans>

测试

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="r" uri="http://shiro.apache.org/tags" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>主界面<%=System.currentTimeMillis()%>,欢迎您:[${sessionScope.username}]</h1>
<ul>
    系统功能列表
    <li>
        <a href="admin/addUser.jsp">用户新增</a>
    </li>
    <li>
        <a href="admin/listUser.jsp">用户查询</a>
    </li>
    <li>
        <a href="admin/resetPwd.jsp">重置用户密码</a>
    </li>
    <li>
        <a href="admin/updateUser.jsp">用户修改</a>
    </li>
    <li>
        <a href="user/updatePwd.jsp">个人密码修改</a>
    </li>
    <li>
        <a href="user/teacher.jsp">老师简介</a>
    </li>
    <li>
        <a href="${pageContext.request.contextPath}/logout">退出系统</a>
    </li>
</ul>
<ul>
    shiro注解
    <ul>
        shiro注解标签
        <li>
            <a href="${pageContext.request.contextPath}/passUser">身份认证</a>
        </li>
        <li>
            <a href="${pageContext.request.contextPath}/passRole">角色认证</a>
        </li>
        <li>
            <a href="${pageContext.request.contextPath}/passPer">权限认证</a>
        </li>
    </ul>
    <li>
        <a href="${pageContext.request.contextPath}/logout">退出系统</a>
    </li>
</ul>
</body>
</html>

Shiro授权-SSM_spring_02
zs只能查看身份认证的按钮内容 其他的不能
Shiro授权-SSM_java_03

ls、ww可以看权限认证按钮内容
Shiro授权-SSM_spring_04
zdm可以看所有按钮的内容

over