【更新】看到很多博客写 shiro权限认证的,都是一半的代码,复制上根本不能使用,依赖文件对于小白来说,更是不知道使用什么依赖,所以我把相应的java文件的包 都一并带上
spring-shiro属于轻量级权限框架,即使spring-security更新换代,市场上大多数企业还是选择shiro
废话不多说 引入pom文件相关依赖
1 23 org.slf4j 4slf4j-api 51.7.16 6
7 89 org.apache.shiro 10shiro-spring 111.3.2 12
导入之后 相关依赖包就会自动加载 shiro-core、shiro-spring、shiro-web等等 依赖版本还得根据shiro集成的spring版本进行加载(注意版本号)
设计登录认证,就少不三张表。没做过登录认证的小白 仔细看,我在Shiro配置中,尽量的去加入注释说明
先贴上我的 用户,角色,权限 三张表的 java 对象
需求分析为:用户角色 - 多对多
角色权限 - 多对多
注意:直接复制的同学,三张表的注解,各位可以忽略删除 也可以学习使用 Spring-Data-Jpa 底层是 Hibernate,建表和查询方便
三个关系告诉你了,其实只需要最后关联的是 : 用户 - 权限 这里不需要 role角色表(实际项目中可以选择需要)

import lombok.Data; import lombok.ToString; @Data @ToString public class User { /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.user_id * * @mbg.generated */ private Integer userId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.user_name * * @mbg.generated */ private String userName; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.password * * @mbg.generated */ private String password; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.phone * * @mbg.generated */ private String phone; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.email * * @mbg.generated */ private String email; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.status * * @mbg.generated */ private Integer status; private String salt; public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.note * * @mbg.generated */ private String note; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.create_time * * @mbg.generated */ private String createTime; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.update_time * * @mbg.generated */ private String updateTime; /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.user_id * * @return the value of tb_users.user_id * * @mbg.generated */ public Integer getUserId() { return userId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.user_id * * @param userId the value for tb_users.user_id * * @mbg.generated */ public void setUserId(Integer userId) { this.userId = userId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.user_name * * @return the value of tb_users.user_name * * @mbg.generated */ public String getUserName() { return userName; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.user_name * * @param userName the value for tb_users.user_name * * @mbg.generated */ public void setUserName(String userName) { this.userName = userName == null ? null : userName.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.password * * @return the value of tb_users.password * * @mbg.generated */ public String getPassword() { return password; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.password * * @param password the value for tb_users.password * * @mbg.generated */ public void setPassword(String password) { this.password = password == null ? null : password.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.phone * * @return the value of tb_users.phone * * @mbg.generated */ public String getPhone() { return phone; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.phone * * @param phone the value for tb_users.phone * * @mbg.generated */ public void setPhone(String phone) { this.phone = phone == null ? null : phone.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.email * * @return the value of tb_users.email * * @mbg.generated */ public String getEmail() { return email; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.email * * @param email the value for tb_users.email * * @mbg.generated */ public void setEmail(String email) { this.email = email == null ? null : email.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.status * * @return the value of tb_users.status * * @mbg.generated */ public Integer getStatus() { return status; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.status * * @param status the value for tb_users.status * * @mbg.generated */ public void setStatus(Integer status) { this.status = status; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.note * * @return the value of tb_users.note * * @mbg.generated */ public String getNote() { return note; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.note * * @param note the value for tb_users.note * * @mbg.generated */ public void setNote(String note) { this.note = note == null ? null : note.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.create_time * * @return the value of tb_users.create_time * * @mbg.generated */ public String getCreateTime() { return createTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.create_time * * @param createTime the value for tb_users.create_time * * @mbg.generated */ public void setCreateTime(String createTime) { this.createTime = createTime; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.update_time * * @return the value of tb_users.update_time * * @mbg.generated */ public String getUpdateTime() { return updateTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.update_time * * @param updateTime the value for tb_users.update_time * * @mbg.generated */ public void setUpdateTime(String updateTime) { this.updateTime = updateTime; } }

import lombok.Data; import lombok.ToString; import java.util.Date; /** * @author wusiwee * @date 2020/4/3 10:58 */ @Data @ToString public class Permission { /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_id * * @mbg.generated */ private Integer funcId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_name * * @mbg.generated */ private String funcName; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_url * * @mbg.generated */ private String funcUrl; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_code * * @mbg.generated */ private String funcCode; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.parent_id * * @mbg.generated */ private Integer parentId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_type * * @mbg.generated */ private Integer funcType; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.status * * @mbg.generated */ private Integer status; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.sort_num * * @mbg.generated */ private Integer sortNum; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.create_time * * @mbg.generated */ private Date createTime; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.update_time * * @mbg.generated */ private Date updateTime; /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_id * * @return the value of tb_functions.func_id * * @mbg.generated */ public Integer getFuncId() { return funcId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_id * * @param funcId the value for tb_functions.func_id * * @mbg.generated */ public void setFuncId(Integer funcId) { this.funcId = funcId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_name * * @return the value of tb_functions.func_name * * @mbg.generated */ public String getFuncName() { return funcName; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_name * * @param funcName the value for tb_functions.func_name * * @mbg.generated */ public void setFuncName(String funcName) { this.funcName = funcName == null ? null : funcName.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_url * * @return the value of tb_functions.func_url * * @mbg.generated */ public String getFuncUrl() { return funcUrl; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_url * * @param funcUrl the value for tb_functions.func_url * * @mbg.generated */ public void setFuncUrl(String funcUrl) { this.funcUrl = funcUrl == null ? null : funcUrl.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_code * * @return the value of tb_functions.func_code * * @mbg.generated */ public String getFuncCode() { return funcCode; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_code * * @param funcCode the value for tb_functions.func_code * * @mbg.generated */ public void setFuncCode(String funcCode) { this.funcCode = funcCode == null ? null : funcCode.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.parent_id * * @return the value of tb_functions.parent_id * * @mbg.generated */ public Integer getParentId() { return parentId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.parent_id * * @param parentId the value for tb_functions.parent_id * * @mbg.generated */ public void setParentId(Integer parentId) { this.parentId = parentId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_type * * @return the value of tb_functions.func_type * * @mbg.generated */ public Integer getFuncType() { return funcType; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_type * * @param funcType the value for tb_functions.func_type * * @mbg.generated */ public void setFuncType(Integer funcType) { this.funcType = funcType; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.status * * @return the value of tb_functions.status * * @mbg.generated */ public Integer getStatus() { return status; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.status * * @param status the value for tb_functions.status * * @mbg.generated */ public void setStatus(Integer status) { this.status = status; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.sort_num * * @return the value of tb_functions.sort_num * * @mbg.generated */ public Integer getSortNum() { return sortNum; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.sort_num * * @param sortNum the value for tb_functions.sort_num * * @mbg.generated */ public void setSortNum(Integer sortNum) { this.sortNum = sortNum; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.create_time * * @return the value of tb_functions.create_time * * @mbg.generated */ public Date getCreateTime() { return createTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.create_time * * @param createTime the value for tb_functions.create_time * * @mbg.generated */ public void setCreateTime(Date createTime) { this.createTime = createTime; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.update_time * * @return the value of tb_functions.update_time * * @mbg.generated */ public Date getUpdateTime() { return updateTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.update_time * * @param updateTime the value for tb_functions.update_time * * @mbg.generated */ public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } }
开始进入Shiro篇
一:自定义Reaml域,用于实现自身认证体系,大白话:什么样的认证规则,我都可以来定
创建Reaml对象 继承 AuthorizingRealm 实现
授权方法
doGetAuthorizationInfo(PrincipalCollection principals){}
认证方法
doGetAuthenticationInfo(AuthenticationToken token){}
import com.bear.entity.Permission; import com.bear.entity.User; import com.bear.service.PermissionService; import com.bear.service.UserService; 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.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.List; /** * @author wusw * @version 1.0 * @date 2020/4/2 19:46 */ public class ShiroReaml extends AuthorizingRealm { /** * 注入userService 服务层 用户与数据库数据查询 */ @Autowired private UserService userService; /** * 注入permissionService 服务层 用户与数据库数据查询 */ @Autowired private PermissionService permissionService; /** * 授权 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //这个User对应下面认证方法的 返回的第一个参数 ew SimpleAuthenticationInfo(user, user.getPassword(), "shiroReaml") User user = (User)principalCollection.getPrimaryPrincipal(); //查询用户相关权限 ListpermissionList = permissionService.findPermissionByUserId(user.getUserId()); //授权对象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //创建一个List 用于接收权限信息 ArrayListlist = new ArrayList<>(); for (Permission permission : permissionList) { //添加权限String字符串:存值示例: "admin:*","admin:list"... info.addStringPermission(permission.getFuncCode()); } return info; } /** * 认证 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //这一块toString返回 username 是login方法在 newUserNamePassword(username,password)创建的token封装成的 String username = token.getPrincipal().toString(); //打印一下,项目中 尽量不要使用System.out.println(),最好使用log日志进行记录 System.out.println("认证获取的username:"+username); //查询数据库用户是否存在 不存在则抛异常 Shiro会自动认证失败 User user = this.userService.findByUsername(username); //参数一 可以传 username,user对象 等等 我这里是user对象 对应上面授权方法principalCollection获取的值 //参数二 用户密码 //参数三 shiroReaml 名称要与 shiroConfig配置中的 Reaml 的注入Bean保持一致 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), "shiroReaml"); return authenticationInfo; } }
二:Shiro配置 加上注解 @Configuration 让springboot识别它为一个配置类
注意:打字太多,我把相应规则的 url 贴上,供大家参考
import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; /** * 请注意看每个方法上的注释 * @author wusw * @version 1.0 * @date 2020/4/2 19:41 */ @Configuration public class ShiroConfig { /** * 添加创建 securityMeneger 工厂注入Bean * @param securityManager 注解Qualifier中的名字 和下面 DefaultWebSecurityManager 的Bean的名字相同 * @return */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager){ ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); filterFactoryBean.setSecurityManager(securityManager); //设置权限过滤器集合 key-value 形式 // key :访问路径 正常/**写在最下面,执行顺序是从上至下,这里是个大坑,一不小心,程序就凉凉了呢~ // value:anon(可以匿名访问),authc(认证后才能访问),logout(退出后自动清除session) HashMapmap = new HashMap<>(); map.put("/bear/login","anon"); map.put("/bear/logout","logout"); map.put("/**","authc"); filterFactoryBean.setLoginUrl("/bear/toLogin"); filterFactoryBean.setUnauthorizedUrl("/bear/401"); filterFactoryBean.setSuccessUrl("/bear/index"); //将map集合 传给过滤器 filterFactoryBean.setFilterChainDefinitionMap(map); return filterFactoryBean; } /** * 创建 securityMeneger 类的注入Bean * @param shiroReaml 注解Qualifier中的名字 和下面 ShiroReaml的Bean的名字相同 * @return */ @Bean("securityManager") public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("shiroReaml") ShiroReaml shiroReaml){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroReaml); return securityManager; } /** * 创建自定义域 reaml注入Bean * @return */ @Bean("shiroReaml") public ShiroReaml shiroReaml(){ return new ShiroReaml(); } }
主要已经搞定,贴上相关service,controller,以及yml配置文件,dao层交互我使用的是mybaties相关pom依赖各位小伙伴自己导入 xml中namespase和type路径请自行导入

# 数据库的配置信息 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://0.0.0.0/db?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong&verifyServerCertificate=false username: *** password: *** type: com.alibaba.druid.pool.DruidDataSource thymeleaf: mode: HTML5 encoding: UTF-8 servlet: content-type: text/html mvc: static-path-pattern: /** # mybatis的配置信息 mybatis: config-location: classpath:mybatis/config/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml server: port: 8081

DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">delete from tb_users where user_id = #{userId,jdbcType=INTEGER} insert into tb_users (user_id, user_name, password, phone, email, status, note, create_time, update_time ) values (#{userId,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, #{note,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP} ) update tb_users set user_name = #{userName,jdbcType=VARCHAR}, password = #{password,jdbcType=VARCHAR}, phone = #{phone,jdbcType=VARCHAR}, email = #{email,jdbcType=VARCHAR}, status = #{status,jdbcType=INTEGER}, note = #{note,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = #{updateTime,jdbcType=TIMESTAMP} where user_id = #{userId,jdbcType=INTEGER}

delete from tb_functions where func_id = #{funcId,jdbcType=INTEGER} insert into tb_functions (func_id, func_name, func_url, func_code, parent_id, func_type, status, sort_num, create_time, update_time) values (#{funcId,jdbcType=INTEGER}, #{funcName,jdbcType=VARCHAR}, #{funcUrl,jdbcType=VARCHAR}, #{funcCode,jdbcType=VARCHAR}, #{parentId,jdbcType=INTEGER}, #{funcType,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, #{sortNum,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}) update tb_functions set func_name = #{funcName,jdbcType=VARCHAR}, func_url = #{funcUrl,jdbcType=VARCHAR}, func_code = #{funcCode,jdbcType=VARCHAR}, parent_id = #{parentId,jdbcType=INTEGER}, func_type = #{funcType,jdbcType=INTEGER}, status = #{status,jdbcType=INTEGER}, sort_num = #{sortNum,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = #{updateTime,jdbcType=TIMESTAMP} where func_id = #{funcId,jdbcType=INTEGER}
dao层:

import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface IUserMapper { /** * 根据用户名查找用户 * @param username * @return */ User findByUsername(String username); /** * 更新 * @param user */ void updateByPrimaryKey(User user); /** * 新增 * @param user */ void insert(User user); /** * 根据id删除用户(后期修改为改变状态) * @param id */ void deleteByPrimaryKey(Integer id); /** * 查询所有用户列表 * @return */ ListfindAll(); }

import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:00 */ @Mapper public interface IPermissionMapper { /** * 根据user id查询用户权限 * @param userId * @return */ ListfindPermissionByUserId(Integer userId); }
service层:

import java.util.List; public interface UserService { User findByUsername(String username); ListfindAll(); }

import com.bear.dao.IUserMapper; import com.bear.entity.User; import com.bear.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl implements UserService { @Autowired private IUserMapper userMapper; @Override public User findByUsername(String username) { User result = null; if (username != null) { result = this.userMapper.findByUsername(username); } return result; } @Override public ListfindAll() { return this.userMapper.findAll(); } }

import com.bear.entity.Permission; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:02 */ public interface PermissionService { ListfindPermissionByUserId(Integer userId); }

import com.bear.dao.IPermissionMapper; import com.bear.entity.Permission; import com.bear.service.PermissionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:02 */ @Service public class PermissionServiceImpl implements PermissionService { @Autowired private IPermissionMapper permissionMapper; @Override public ListfindPermissionByUserId(Integer userId) { List result = null; if (userId != null) { result = this.permissionMapper.findPermissionByUserId(userId); } return result; } }
controller层(注意Login方法的subject为shiro登录使用):
注解@RequiresPermissions("system:*")为校验用户是否有权限,没有此权限则不允许访问此方法 跳转401

import com.bear.service.UserService; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/bear") public class LoginController { @Autowired private UserService userService; @GetMapping("toLogin") public String toLogin(){ return "login"; } @GetMapping("/login") public String login(String username, String password, Model model){ if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)){ //进行登录验证 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); //认证 boolean authenticated = subject.isAuthenticated(); if (authenticated){ //获取当前对象,存入session User user = (User)subject.getPrincipal(); subject.getSession().setAttribute("user",user); System.out.println("登陆成功"); return "redirect:index"; }else { model.addAttribute("msg","登录认证失败!"); return "login"; } }catch (Exception e){ model.addAttribute("msg","登录认证失败!"); return "login"; } } return "login"; } @RequestMapping("/index") public String index(Model model){ model.addAttribute("userList",this.userService.findAll()); return "index"; } @RequestMapping("/logout") public String index(){ return "redirect:login"; } @RequestMapping("/401") public String fours(){ return "401"; } @RequiresPermissions("system") @RequestMapping("/success") public String success(){ return "success"; } }
html 页面:

成功页面 SUCCESS!

登录页面 欢迎来到登录页面!

首面 用户列表页面
用户ID | 用户名 | 手机号 | 邮箱 | 状态 | 创建时间 |
正常 |

401没有认证 抱歉,您的权限不足或认证失败,请重新登录!
配置完成
启动运行Applicaiton.java,最后一行,启动成功

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.6.RELEASE) 2020-04-07 15:11:42.580 INFO 14672 --- [ main] com.bear.PublicApplication : Starting PublicApplication on shands-siwee with PID 14672 (D:\java\GitProjects\bear-world\target\classes started by Shands-New in D:\java\GitProjects\bear-world) 2020-04-07 15:11:42.584 INFO 14672 --- [ main] com.bear.PublicApplication : No active profile set, falling back to default profiles: default 2020-04-07 15:11:43.534 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.bear.shiro.ShiroConfig$$EnhancerBySpringCGLIB$$45102fe0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.599 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties' of type [org.mybatis.spring.boot.autoconfigure.MybatisProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.604 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration' of type [org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$6a2f2642] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.605 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.617 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.665 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [com.alibaba.druid.pool.DruidDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.677 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.923 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.926 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.928 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IUserMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.929 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IUserMapper' of type [com.sun.proxy.$Proxy63] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.929 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'userServiceImpl' of type [com.bear.service.impl.UserServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IPermissionMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IPermissionMapper' of type [com.sun.proxy.$Proxy64] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'permissionServiceImpl' of type [com.bear.service.impl.PermissionServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.933 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'shiroReaml' of type [com.bear.shiro.ShiroReaml] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:44.601 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'securityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:44.857 INFO 14672 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2020-04-07 15:11:44.868 INFO 14672 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2020-04-07 15:11:44.868 INFO 14672 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33] 2020-04-07 15:11:45.041 INFO 14672 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-04-07 15:11:45.042 INFO 14672 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2400 ms 2020-04-07 15:11:45.231 INFO 14672 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-04-07 15:11:45.301 INFO 14672 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index 2020-04-07 15:11:45.356 WARN 14672 --- [ main] org.thymeleaf.templatemode.TemplateMode : [THYMELEAF][main] Template Mode 'HTML5' is deprecated. Using Template Mode 'HTML' instead. 2020-04-07 15:11:45.455 INFO 14672 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '' 2020-04-07 15:11:45.458 INFO 14672 --- [ main] com.bear.PublicApplication : Started PublicApplication in 3.516 seconds (JVM running for 4.842)
测试访问 :localhost:8081/bear/index ——>此时是被拦截的,会自动跳转toLogin到登录页面