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>
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> <!–逆向工程的主要包–> <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>--> </generatorConfiguration>
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更倾向于 与数据库 本地 进行交互。 请求先到达过滤器再到拦截器 -->
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中的配置更偏向与 后台代码逻辑与前台展示之间-->
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>
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> -->
自定义的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; } }
8.前台用于验证的一些html
8.1.认证过的用户,访问未授权的路径,跳转的结果。何时出发 看 controller 中的代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 没有权限 </body> </html>
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>
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>
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; } }