shiro三连斩之第二斩(SSM)

在SSM框架中使用shiro。环境 使用idea工具。

最主要的大概是配置文件如何配置吧。

1配置maven依赖

<?xml version="1.0" encoding="UTF-8"?>

<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>com</groupId>
    <artifactId>shirodemo2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>shirodemo2 Maven Webapp</name>
    <!-- FIXME change it to the project‘s website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--shiro需要用的依赖包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!--spring需要的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--json数据格式转换-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.14</version>
        </dependency>
        <!--切面编程需要用到-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>shirodemo2</finalName>
        <!--mybatis逆向工程-->
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <overwrite>true</overwrite>
                    <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.47</version>
                    </dependency>
                </dependencies>

            </plugin>
        </plugins>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

pom.xml

2.使用mybatis逆向工程 生成实体类

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--逆向工程配置文件,通过在pom.xml的依赖于引用来根据数据库中的表生成实现类与dao接口以及映射文件-->
    <context id="mysql" targetRuntime="Mybatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/bcs"
                        userId="root" password="">
        </jdbcConnection>
        <!--存放生成实体类的路径,在idea中targetProject填写生成地址,eclipse中填写项目名-->
        <javaModelGenerator targetPackage="com.bpms.pojo" targetProject="src/main/java"/>
        <!--生成sql映射文件的路径,在idea中,文件会被标记,资源放到resources中,mapper.xml放到java中的话,需要在pom.xml进行额外配置-->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>
        <!--生成dao接口的目录,dao 数据访问对象,面向对象的数据访问接口-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.bpms.dao" targetProject="src/main/java"/>
        <!--接口映射名可以自动生成 mapperName,也可以手动设置-->
        <!--tableName:数据库中的表名,mapperName:dao接口及mapper.xml映射文件名,domainObjectName:pojo实体类名-->
        <table tableName="t_auth" domainObjectName="Auth" enableDeleteByExample="false"
               enableUpdateByExample="false"
               enableSelectByExample="false"
               enableCountByExample="false"
               selectByExampleQueryId="false"/>

        <table tableName="t_user" domainObjectName="User" enableDeleteByExample="false"
               enableUpdateByExample="false"
               enableSelectByExample="false"
               enableCountByExample="false"
               selectByExampleQueryId="false"/>
        <table tableName="t_role" domainObjectName="Role" enableDeleteByExample="false"
               enableUpdateByExample="false"
               enableSelectByExample="false"
               enableCountByExample="false"
               selectByExampleQueryId="false"/>

    </context>
    <!--添加在pom.xml的build节点下的内容。-->
    <!--<plugins>
        <plugin>
            &lt;!&ndash;逆向工程的主要包&ndash;&gt;
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <overwrite>true</overwrite>
                <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
            </configuration>
            &lt;!&ndash;要与数据库进行连接。依赖的驱动&ndash;&gt;
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.47</version>
                </dependency>
            </dependencies>

        </plugin>
    </plugins>-->
</generatorConfiguration>

generatorConfig.xml

3.创建applicationContext.xml  spring-mvc.xml spring-shiro.xml 。注意,创建的xml,以箭头指示的插件来创建。

  三个xml文件直接放在,resources目录下就好。后面再开始配置

4配置web.xml 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--web.xml 的加载顺序是:ServletContext -> context-param -> listener -> filter -> servlet ,而同个类型之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。-->
    <!--部署applicationContext的xml文件,如果在web.xml中不写任何参数配置信息,默认的路径是"/WEB-INF/applicationContext.xml,自定义文件名可以在web.xml里加入contextConfigLocation这个context参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:spring-shiro.xml</param-value>
    </context-param>
    <!--ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--过滤器配置的顺序,过滤器最好配置的位置是在org.springframework.web.filter.CharacterEncodingFilter 之后,就是处理好字符集就是Shiro的过滤器。这里没有进行处理-->
    <filter>
        <filter-name>shiroFilter</filter-name><!--这个shiroFilter不能随便,在spring-shiro.xml中ShiroFilterFactoryBean的id要一致-->
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--使用Spring MVC,配置DispatcherServlet是第一步。DispatcherServlet是一个Servlet,,所以可以配置多个DispatcherServlet-->
    <!--DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。-->
    <!--在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指明了配置文件的文件名,不使用默认配置文件名,而使用dispatcher-servlet.xml配置文件。-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <!--是启动顺序,让这个Servlet随Servlet容器一起启动。-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
        <!--在web.xml中要注入的配置文件 有三个 applicationContext(1) spring-mvc(2) spring-shiro(3),但是 1 2 3 却不在一起
            1 3 在 context 标签中 最先加入的  。2在servlet标签中 设置了加载优先级。还是没有 context中的优先。
            一般 2 更倾向于 与网络 Tomcat 交互  。1 3更倾向于 与数据库 本地 进行交互。
            请求先到达过滤器再到拦截器
         -->

web.xml

5.配置applicationContext.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"
       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.xsd">
    <!--表示启动spring的组件扫描功能(从spring2.5版本开始)。即扫描base-package包或者子包下面的Java文件,如果扫描到有@controller、@Service、@Repository、@Component等注解的java类,就会将这些bean注册到工厂中。
    还可以使用分号来分隔多个扫描包。如果在配置文件中配置了<context:component-scan />,就不用在配置<context:annotation-config/>,因为前者已经包含了后者。<context:annotation-config/>的作用是向spring容器注入
    AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 及RequiredAnnotationBeanPostProcessor 四个beanPostProcessor。从而使得@Autowired等注解生效。-->
    <context:component-scan base-package="com.*"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
        <property name="url" value="jdbc:mysql://localhost:3306/bcs"/>
    </bean>

    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <!--sql文件映射路径-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>
    <!-- 自动扫描注册mapper接口类(接口类实现mybatis),根据 sessionFactory对应的mapperLocations生成接口类的实现-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bpms.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sessionFactory"/><!--这个是value值不是ref映射-->
    </bean>
    <!--以上是主要是把mybatis中的配置使用applicationContext来进行。连接数据库相关的信息。包括 -->
</beans>
<!--个人认为,在applicationContext中进行的配置的。更偏向与后台代码逻辑与数据库之间,spring-mvc.xml中的配置更偏向与 后台代码逻辑与前台展示之间-->

applicationContext.xml

6.配置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.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">
    <!-- 使用组件扫描的方式可以一次扫描多个Controller,自动扫描方式,扫描包下面所有的Controller,可以使用注解来指定访问路径 -->
    <context:component-scan base-package="com.bpms"/>
    <!-- 配置注解的处理器映射器和处理器适配器 -->
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置spring shiro 支持aop注解-->
    <!--true针对类进行代理-->
    <aop:config proxy-target-class="true"/>
    <!--配置使aop注解生效的通知,securityManager的详细配置在spring-shiro.xml中进行-->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!--静态资源的请求-->
    <mvc:resources mapping="/**" location="/"/>
</beans>

spring-mvc.xml

7.配置spring-shiro.xml   编写 realm

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <!--配置shiro过滤器;id必须与web.xml中一致,对远程来访问的的 url 按照一定的格式进行匹配-->
    <bean class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" id="shiroFilter">
        <!-- 没有登录重定向到登录页面 -->
        <property name="loginUrl" value="/login.html"/>
        <!-- 没有权限跳转的页面 -->
        <property name="unauthorizedUrl" value="/403.html"/>
        <!-- shiro拦截器 -->
        <!--anon(都是shiro提供的filter):匿名访问(没有登录的情况下也可以访问),一般用来忽略静态资源
            authc:必须要认证以后才能访问的
            logout:注销要用到的-->
        <property name="filterChainDefinitions">
            <value>
                /login.html=anon
                /css/*=anon
                /static/*=anon
                /js/*=anon
                /doLogin=anon
                /*=authc
            </value>
        </property>
        <!-- 调用我们配置的权限管理器 -->
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!--配置安全管理器,注入域,缓存,remember会话都在这里注入,需要注入到 在spring-mcv中配置的对象中-->
    <bean class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" id="securityManager">
        <property name="realm" ref="customRealm"/>
        <property name="cacheManager" ref="cacheManager"/>
    </bean>

    <!--自定义域,可以在bean外面配置再添加进来,也可以在直接在bean里面配置-->
    <bean class="com.bpms.shiro.CustomRealm" id="customRealm">
        <property name="credentialsMatcher" ref="matcher"/>
    </bean>

    <!--加密算法与次数-->
    <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="matcher">
        <property name="hashAlgorithmName" value="md5"/>
        <!--之前的加密次数没有设置,这里注释掉-->
        <!--<property name="hashIterations" value="2"/>-->
    </bean>

    <!--缓存-->
    <bean class="org.apache.shiro.cache.MemoryConstrainedCacheManager" id="cacheManager"/>
</beans>
        <!-- 启动shiro注解(必须放在spring MVC 配置文件那边) -->
        <!-- <aop:config proxy-target-class="true"></aop:config>
        可以配置在shiro或springmvc这里
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" >
        <property name="securityManager"  ref="securityManager"></property>
        </bean> -->

spring-shiro.xml

自定义的realm

package com.bpms.shiro;

import com.bpms.pojo.User;
import com.bpms.service.AuthService;
import com.bpms.service.UserService;
import org.apache.shiro.authc.*;
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 java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private AuthService authService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User user = (User) principalCollection.getPrimaryPrincipal();
        //认证通过的话,是否到达授权
        List<String> perms = authService.findPermsByUserName(user.getUserName());//连接服务层从数据库中查找权限添加进来
        System.out.println("当前用户拥有的权限许可:");
        for (String str : perms) {
            System.out.println(str + "------授权");
        }

        Set set = new HashSet(perms);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(set);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = (String) authenticationToken.getPrincipal();
        System.out.println("认证userName:" + userName);//前台的数据是否传到身份认证这里
        User user = userService.findUserByName(userName);
        System.out.println("数据库用户:" + user);
        if (user == null) {
            throw new UnknownAccountException("当前用户不存");
        }
        //把根据用户名查找到的密码作为参数,与根据登录时传的数据生成的token进行匹配
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
        //如果加密了,必须指定盐值
        info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
        return info;
    }
}

CustomRealm.java

8.前台用于验证的一些html

  8.1.认证过的用户,访问未授权的路径,跳转的结果。何时出发 看 controller 中的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
没有权限
</body>
</html>

403.xml

  8.2.登录界面,未进行认证需求。即不认证也可以进行访问,不然登不进来。(访问登录界面,登录界面方法的认证路径,退出,等都不需要设置认证)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="doLogin" method="post">
        用户名:<input type="text" name="userName"> <br>
        密码: <input type="password" name="password"> <br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

login.html

  8.3,shiro前端对用户权限的一些操作,不难,需要记一下。也是登录,认证成功时跳转的页面

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<body>
<h2>Hello World!</h2>
<%--获取当前登录用户的用户名,登陆成功,信息通过token保存在 shiro的session域中--%>
welcome <shiro:principal property="userName"> </shiro:principal>!!!!
<br>
需要认证的连接 <br>
<shiro:hasPermission name="sys:user:list">
    <a href="list">查看</a>
</shiro:hasPermission>

<shiro:hasPermission name="sys:role:delete">
    <a href="delete">删除</a>
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:update">
    <a href="update">修改</a>
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:save">
    <a href="insert">添加</a>
</shiro:hasPermission>
<br>
不需要认证的连接<br>
<a href="delete">delete</a>

<a href="logout">退出系统</a>

<p>
    数据库中admin用户是系统管理员 <br>
    拥有的权限id 1,2,12,13,14,15,16,31,32<br>
    权限id 中,有许可的都是下面这些<br>
    sys:role:list
    sys:role:save
    sys:role:update
    sys:role:delete<<br>
    对应的上述的 shiro 标签,如果admin用户拥有的许可中有能与 shiro 标签中要求的的许可匹配,就会显示。shiro标签包含的内容<br>
    这个用于在前台隐藏访问路径。如果有人知道,之前通过http进行请求,需要在后台进行认证
</p>
<p>
    @RequiresPermissions({"sys:user:delete"})<br>
    如果前台的访问的路径需要认证被shiro拦截之后。当前用户已经通过认证。<br>
    如果访问的路径被前端控制器,转发到相应的handler 中。对应的方法有这个注解。<br>
    说明。需要这个认证过的用户,要有这个权限 "sys:user:delete",才可以进入 handler中。<br>
    "sys:user:delete"这样写只是一种规范,只要在realm中给该用户授权的 字段 和对应handler要求的字段一致,就可以进入handler。

</p>

</body>
</html>

index.html

9.后台对认证过的用户,权限限制的配置。通过不同的注解,对权限或者角色(还可以附加 与 或的关系)

@RequiresAuthentication 表示当前Subject已经通过login进行了身份验证;即Subject. isAuthenticated()返回true。

@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)

表示当前Subject需要角色admin和user。

@RequiresPermissions (value={“user:update”, “user:delete”}, logical= Logical.OR)

表示当前Subject需要权限user:update或user:delete

package com.bpms.controller;

import com.bpms.pojo.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class UserController {

    @RequestMapping("/doLogin")
    public String doLogin(User user) {
        System.out.println("doLogin:" + user);//用于检测请求是否走到了这一步,并查看请求的信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
        try {
            Md5Hash md5Hash = new Md5Hash(user.getPassword(), "admin");
            System.out.println(md5Hash.toString());//因为密码不对,按照自己定义的加密方式,获得加密的密码,更新到数据库中。
            subject.login(token);
            return "redirect:/index.jsp";
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return "redirect:/login.html";
        }

    }

    @RequestMapping("/logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "redirect:/login.html";
    }

    @RequestMapping("/insert")
    @ResponseBody
    public String insert() {
        return "insert";
    }

    @RequestMapping("/delete")
    @ResponseBody
    @RequiresPermissions({"sys:user:delete"})//需要被认证的用户拥有的 权限 中有可以匹配 该字段的。请求才可以进入方法中
    public String delete() {                  //防止前台没有显示访问路径的时候,通过url恶意访问
        return "delete";
    }

    @RequestMapping("/list")
    @ResponseBody
    public String list() {
        return "list";
    }

    @RequestMapping("/update")
    @ResponseBody
    public String update() {
        return "update";
    }

    @ExceptionHandler(UnauthorizedException.class)//认证的过用户,访问了没有权限的handler,进不去时,跳转的页面(一般页面进行了限制,触发这个很可能时恶意访问)
    public ModelAndView unauthorizedException() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/403.html");
        return modelAndView;
    }

}

UserController

原文地址:https://www.cnblogs.com/xiaoeyu/p/10460529.html

时间: 2024-10-17 08:42:38

shiro三连斩之第二斩(SSM)的相关文章

shiro三连斩之第三斩,整合 springboot

shiro爱springboot中使用 ,还有thymeleaf前端框架.主要是如何配置 pom.xml配置依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:s

《CLR.via.C#第三版》第二部分第4,5章节读书笔记(二)

这两章全是理论性的东西,我觉得不必过于钻牛角尖.理论这东西,只有在长期的实践中去慢慢领悟才会深刻.下面我只写些我认为重要的关键知识. (一)类型转换 知识点:向基类型的转换被认为是一种安全的隐式转换:向派生类型转换时,只能显示转换. 举例: Object o = new Employee(); Employee e = (Employee)o; 重要认知:CLR的类型检查会遍历继承层次结构,用每个基类型去核对指定的类型. 常用代码:(见下方代码段.CLR会检查两次对象的类型): if(o is

程序员表白程序,开放源码,不断更新(第三篇:第二弹)

首先感谢hackerzhou同志,是他给了我激情和想法,感谢他的开源精神,造福大家. 这一波主要内容集中在网页这里,我一直想找一个通用或简易办法,能使大部分人都能使用"表白"这份礼物,如果使用网页,那么就要会建站,要服务器,要域名,除了代码还需要配置,有点麻烦,我这里使用的都是新浪云服务器,可以免费建一些网站,操作也比较简单,不会建站的可以来问我. 这一章的主要内容是展示这些表白的页面. 一.loveyue1 演示地址:http://loveyue1.sinaapp.com 效果如图:

《CLR.via.C#第三版》第二部分第8,9章节读书笔记(四)

三种类型的构造方法: 实例构造器(引用类型):实例构造器永远不能被继承(所以方法前没有修饰符):如果类的修饰符为static(sealed和abstract),编译器根本不会在类的定义中生成一个默认构造器. 重要认知:为了使代码“可验证”,类的实例构造器在访问从基类继承的任何字段之前,必须先调用基类的构造器.如果派生类的构造器没有显示调用一个基类构造器,C#编译器会自动生成对默认的基类构造器的调用. 在类中声明的字段,实际在编译器中是转换成构造器中的代码执行初始化.如果一个类中有3个字段,3个构

《CLR.via.C#第三版》第二部分第6,7章节读书笔记(三)

第6章讲的是类型和成员基础 重要认知:虚方法 虚方法的设计原则:设计一个类型时,应尽量减少所定义的虚方法的数量. 首先,调用虚方法的速度比调用非虚方法慢. 其次,JIT编译器不能内嵌虚方法,这进一步影响了性能. 第三,虚方法使组件的版本控制变得更脆弱. 第四,定义一个基类时,如果希望一些方法是多态的,最好的办法是使复杂的办法成为虚方法,简便的成为非虚方法. 引申到定义类时应遵循的原则: 1. 定义类时,除非确定要将此类作为基类使用,否则总是显示指定为sealed类:      2. virtua

UISCrollView —— 图片轮播器实现(三)——(第二讲)

1. 所用知识点 1> UIScrollView的基本属性,和UIPageControl设置,还有就是要用到NSTimer来定时实现UIScrollView的图片轮播 2> NSTimer简单介绍: 2.1  NSTimer叫做“定时器”,它的作用如下 * 在指定的时间执行指定的任务 * 每隔一段时间执行指定的任务 2.2  NSTimer简单使用: 1> 调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTimerWithTimeInterval:(NST

JavaScript高级程序设计(第三版)第二章 在HTML中使用JavaScript

2.1 <script>元素 <script>定义了下列6个属性: async:可选.表示应该立即下载脚本,但不应妨碍页面的其他操作,比如下载其他资源或等待加载其他脚本.只对外本脚本文件有效. charset:可选.表示通过src属性指定的代码的字符集.由于大多数浏览器会忽略它的值,因此这个属性很少使用. defer:可选.表示脚本可以延迟到文档完全被解析和显示之后再执行.只对外部脚本文件有效.IE7及更早版本对嵌入脚本也支持这个属性. language:已废弃. src:可选.表

第三周 习题第二部分

4. 5. (1)电枢电压降低一半 (2)电枢电路串联4欧姆电阻 (3)励磁电压降低一半

《CLR.via.C#第三版》第二部分第13章节 接口 读书笔记(七)

这章的书写感觉很普通,是些基础的认知知识. 其中一点的重要认知,泛型接口的好处(其实也是使用泛型的好处之一):编译时类型安全&处理值类型时减少装箱. 再说点书上没有的.本来这些知识我打算另外分类在C#基础里讲的,这里先单独表述下. 接口回调 其实我想不通为什么这本书不讲一下接口回调这个概念,我可不会相信接口回调只在java中用到. 到现在为止,我突然发现,很多编程的基础概念,于面向对象编程的语言来说,都是通用的,但是抱歉,在C#里(相关书籍)居然没有!但我相信你翻阅Java书籍就有很大几率看到这