shiro权限登录案例
shiro登录案例
流程:从登陆页面访问进入controller,获取对象主体,在shiro.config中配置过滤器工厂(getShiroFilterFactoryBean),这里进行系统资源配置,注册安全管理器,注册自定义realm,进行md5加密,配置shiro缓存,在realm中,配置认证器、授权器,但是登陆首先是使用认证器,密码使用md5,并且加盐处理,与数据库账号密码匹配。验证成功,重定向到index.jsp,当访问页面时,重新被拦截,授权器拿到登陆后的用户信息,通过用户id去查找该用户对应的角色,通过该角色查询相应的权限,结果返回给授权器,index.jsp根据查询到的权限资源,如果权限有则显示,没有则不显示。
数据库
/* Navicat MySQL Data Transfer Source Server : localHost Source Server Version : 50726 Source Host : localhost:3306 Source Database : shiro Target Server Type : MYSQL Target Server Version : 50726 File Encoding : 65001 Date: 2020-12-18 17:00:47 */ create database `shiro` character set utf8; SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for t_perms -- ---------------------------- DROP TABLE IF EXISTS `t_perms`; CREATE TABLE `t_perms` ( `id` int(6) NOT NULL AUTO_INCREMENT, `name` varchar(80) DEFAULT NULL, `url` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_perms -- ---------------------------- INSERT INTO `t_perms` VALUES ('1', 'user:*:*', ''); INSERT INTO `t_perms` VALUES ('2', 'product:*:01', null); INSERT INTO `t_perms` VALUES ('3', 'order:*:*', null); -- ---------------------------- -- Table structure for t_role -- ---------------------------- DROP TABLE IF EXISTS `t_role`; CREATE TABLE `t_role` ( `id` int(6) NOT NULL AUTO_INCREMENT, `name` varchar(60) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_role -- ---------------------------- INSERT INTO `t_role` VALUES ('1', 'admin'); INSERT INTO `t_role` VALUES ('2', 'user'); INSERT INTO `t_role` VALUES ('3', 'product'); -- ---------------------------- -- Table structure for t_role_perms -- ---------------------------- DROP TABLE IF EXISTS `t_role_perms`; CREATE TABLE `t_role_perms` ( `id` int(6) NOT NULL, `roleid` int(6) DEFAULT NULL, `permsid` int(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_role_perms -- ---------------------------- INSERT INTO `t_role_perms` VALUES ('1', '1', '1'); INSERT INTO `t_role_perms` VALUES ('2', '1', '2'); INSERT INTO `t_role_perms` VALUES ('3', '2', '1'); INSERT INTO `t_role_perms` VALUES ('4', '3', '2'); INSERT INTO `t_role_perms` VALUES ('5', '1', '3'); -- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(6) NOT NULL AUTO_INCREMENT, `username` varchar(40) DEFAULT NULL, `password` varchar(40) DEFAULT NULL, `salt` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES ('1', 'xiaochen', 'ca9f1c951ce2bfb5669f3723780487ff', 'IWd1)#or'); INSERT INTO `t_user` VALUES ('2', 'zhangsan', 'ca9f1c951ce2bfb5669f3723780487ff', 'IWd1)#or'); INSERT INTO `t_user` VALUES ('3', 'apple', '9bb1eb6cec8c67bad76436f7610f68af', 'FNLwK00X'); INSERT INTO `t_user` VALUES ('4', 'apple', '962831c7c6c7a4a2fee3341ae164d448', '$8Uka!yM'); -- ---------------------------- -- Table structure for t_user_role -- ---------------------------- DROP TABLE IF EXISTS `t_user_role`; CREATE TABLE `t_user_role` ( `id` int(6) NOT NULL, `userid` int(6) DEFAULT NULL, `roleid` int(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_user_role -- ---------------------------- INSERT INTO `t_user_role` VALUES ('1', '1', '1'); INSERT INTO `t_user_role` VALUES ('2', '2', '2'); INSERT INTO `t_user_role` VALUES ('3', '2', '3');
依赖配置
pom.xml中,引入shiro和ehcache相关依赖
<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.demo</groupId> <artifactId>shiro-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <!-- 配置web依赖 jar --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 内嵌tomcat配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- servlet和jsp的依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- mysql支持 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency> <!-- mybatis框架 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <!-- 热部署,不重启启动就更新项目 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional><!-- true代表热部署生效 --> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency> <!--引入shiro整合springboot依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.5.3</version> </dependency> <!--引入shiro和ehcache --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.5.3</version> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
文件配置
包含端口配置8080,访问路径/shiro,连接池的配置,实体取别名(这里在xml中,resultType就不用写全路径名字了),mapper映射配置
server.port=8080 #web-context server.context-path=/shiro #页面访问路径 spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp #连接池配置 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/shiro?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=root #实体取别名 mybatis.type-aliases-package=com.demo.entity #mapper配置 mybatis.mapper-locations=classpath:com/mapper/*.xml
启动类
启动类要注意,main方法中是本类的.class,同时这个类也是启动springboot整个项目的启动类
package com.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.support.SpringBootServletInitializer; //容器启动配置类 @SpringBootApplication @ServletComponentScan public class SpringbootApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(SpringbootApplication.class); } public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
一般工程目录结构
实体类
Role.java
//角色 @Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class Role implements Serializable { private String id; private String name; //定义权限的集合 private List<Perms> perms; }
User.java
//用户 @Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private String id; private String username; private String password; private String salt; //定义角色集合 private List<Role> roles; }
Param.java
//权限 @Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class Perms implements Serializable { private String id; private String name; private String url; }
业务层
service.java,serviceImpl.java
public interface UserService { //注册用户方法 void register(User user); //根据用户名查询业务的方法 User findByUserName(String username); //根据用户名查询所有角色 User findRolesByUserName(String username); //根据角色id查询权限集合 List<Perms> findPermsByRoleId(String id); }
@Service("userService") @Transactional public class UserServiceImpl implements UserService { //这里又封装了一dao层 @Autowired private UserDAO userDAO; //通过角色id获取权限列表集合 @Override public List<Perms> findPermsByRoleId(String id) { return userDAO.findPermsByRoleId(id); } //通过用户名拿角色 @Override public User findRolesByUserName(String username) { return userDAO.findRolesByUserName(username); } //通过用户名拿用户 @Override public User findByUserName(String username) { return userDAO.findByUserName(username); } //注册业务 @Override public void register(User user) { //处理业务调用dao //1.生成随机盐 String salt = SaltUtils.getSalt(8); //2.将随机盐保存到数据 user.setSalt(salt); //3.明文密码进行md5 + salt + hash散列 Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024); user.setPassword(md5Hash.toHex()); userDAO.save(user); } }
UserDao.java
@Mapper public interface UserDAO { void save(User user); User findByUserName(String username); //根据用户名查询所有角色 User findRolesByUserName(String username); //根据角色id查询权限集合 List<Perms> findPermsByRoleId(String id); }
UserDAOMapper.xml
这里使用了一对多的关系,collection连接表。通过用户名获取角色集合,通过角色获取权限的id
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.demo.dao.UserDAO"> <!-- 注册用户 useGeneratedKeys="true" keyProperty="id" 这个配置可以在增加一条数据后,直接获取到刚才插入数据库中的id --> <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into t_user values(#{id},#{username},#{password},#{salt}) </insert> <!-- 通过名称查询姓名和密码 --> <select id="findByUserName" parameterType="String" resultType="User"> select id,username,password,salt from t_user where username = #{username} </select> <resultMap id="userMap" type="User"> <id column="uid" property="id"/> <result column="username" property="username"/> <!--角色信息--> <collection property="roles" javaType="list" ofType="Role"> <id column="id" property="id"/> <result column="rname" property="name"/> </collection> </resultMap> <!-- 通过用户名称查询角色信息数据集合,返回用户对象 --> <!--这里是三张表进行联合查询 由于表之间是多对多的 所以中间有一张表进行连接 --> <select id="findRolesByUserName" parameterType="String" resultMap="userMap"> SELECT u.id uid,u.username,r.id,r.NAME rname FROM t_user u LEFT JOIN t_user_role ur ON u.id=ur.userid LEFT JOIN t_role r ON ur.roleid=r.id WHERE u.username=#{username} </select> <!-- 通过角色获取权限集合 --> <!--三张表联合查询 --> <select id="findPermsByRoleId" parameterType="String" resultType="Perms"> SELECT p.id,p.NAME,p.url,r.NAME FROM t_role r LEFT JOIN t_role_perms rp ON r.id=rp.roleid LEFT JOIN t_perms p ON rp.permsid=p.id WHERE r.id=#{id} </select> </mapper>
认证、授权
controller.java
package com.demo.controller; import javax.servlet.http.HttpSession; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; 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 com.demo.entity.User; import com.demo.service.UserService; @Controller @RequestMapping("user") public class UserController { @Autowired private UserService userService; /** * 用户注册 */ @RequestMapping("register") public String register(User user) { try { userService.register(user); return "redirect:/login.jsp"; } catch (Exception e) { e.printStackTrace(); return "redirect:/register.jsp"; } } /** * 退出登录 */ @RequestMapping("logout") public String logout() { Subject subject = SecurityUtils.getSubject(); subject.logout();// 退出用户 return "redirect:/login.jsp"; } /** * 用来处理身份认证 * * @param username * @param password * @return */ @RequestMapping("login") public String login(String username, String password, String code, HttpSession session) { try { // 获取主体对象 Subject subject = SecurityUtils.getSubject(); // 认证token 这里调用这个login方法的时候 就会执行 realm中的认证方法 subject.login(new UsernamePasswordToken(username, password)); return "redirect:/index.jsp"; //这里认证器通过以后 就会进入主页面 这时候分配权限 //下述报错说明其他错误 重新登陆 } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误!"); } catch (IncorrectCredentialsException e) { e.printStackTrace(); System.out.println("密码错误!"); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); } return "redirect:/login.jsp"; } }
shiro配置,shiro.config。过滤器配置资源、安全管理器、获取自定义域realm
package com.demo.shiro.config; import java.util.HashMap; import java.util.Map; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.realm.Realm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.demo.shiro.realm.CustomerRealm; //用来整合shiro框架相关配置类 //使用spring注解自动注入的功能,调用getXX,注入setXX @Configuration public class ShiroConfig { // shiroFilter 负责拦截所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 给filter设置安全管理器 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); // 配置系统受限资源 // 配置系统公共资源 Map<String, String> map = new HashMap<String, String>(); map.put("/user/login", "anon");// anon 设置为公共资源 放行资源放在下面 map.put("/user/register", "anon");// anon 设置为公共资源 放行资源放在下面 map.put("/register.jsp", "anon");// anon 设置为公共资源 放行资源放在下面 // /** 受限资源 不受限的资源放在上面 map.put("/**", "authc");// authc 请求这个资源需要认证和授权 /**拦截所有资源 // 如果没有认证成功就会重定向默认认证界面路径 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } // 2.创建安全管理器 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) { //安全管理器 DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); // 给安全管理器设置realm defaultWebSecurityManager.setRealm(realm); return defaultWebSecurityManager; } // 3.创建自定义realm @Bean public Realm getRealm() { CustomerRealm customerRealm = new CustomerRealm(); // 修改凭证校验匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); // 设置加密算法为md5 credentialsMatcher.setHashAlgorithmName("MD5"); // 设置散列次数 credentialsMatcher.setHashIterations(1024); customerRealm.setCredentialsMatcher(credentialsMatcher); //开启缓存管理 //缓存默认实现 缓存的目的是为了让权限存在缓存 下次方便取 customerRealm.setCacheManager(new EhCacheManager()); customerRealm.setCachingEnabled(true);//开启全局缓存 customerRealm.setAuthenticationCachingEnabled(true);//认证认证缓存 customerRealm.setAuthenticationCacheName("authenticationCache"); customerRealm.setAuthorizationCachingEnabled(true);//开启授权缓存 customerRealm.setAuthorizationCacheName("authorizationCache"); return customerRealm; } }
创建自定义域CustomerRealm.java,授权器和认证器,在用户登陆的时候会进行认证器验证账号密码,在登陆完成以后会找到用户对应角色,每个角色所拥有的权限,添加到域中,返回授权器。
package com.demo.shiro.realm; //自定义realm 拿到数据库账号密码的地方 public class CustomerRealm extends AuthorizingRealm { //授权器 给用户赋给权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //获取身份信息 String primaryPrincipal = (String) principals.getPrimaryPrincipal(); System.out.println("调用授权验证: "+primaryPrincipal); //根据主身份信息获取角色 和 权限信息 UserService userService = (UserService) ApplicationContextUtils .getBean("userService"); //这里根据用户名 查到该用户具有哪些角色 User user = userService.findRolesByUserName(primaryPrincipal); //授权角色信息 角色存在 if(!CollectionUtils.isEmpty(user.getRoles())){ //这里说明有很多个角色 //拿到授权器 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); user.getRoles().forEach(role->{ //这里给每个角色赋权限 simpleAuthorizationInfo.addRole(role.getName()); //权限信息 更具角色的id 查到该角色拥有的所有权限点 List<Perms> perms = userService.findPermsByRoleId(role.getId()); if(!CollectionUtils.isEmpty(perms)){ perms.forEach(perm->{ //将权限放到变量中 拿到权限对象的权限名字 添加到可访问域中 simpleAuthorizationInfo.addStringPermission(perm.getName()); }); } }); //返回授权器 return simpleAuthorizationInfo; } return null; } //认证器 用户密码登陆验证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("=========================="); //根据身份信息 String principal = (String) token.getPrincipal(); //在工厂中获取service对象 UserService userService = (UserService) ApplicationContextUtils.getBean("userService"); //根据用户名 查到对应的用户对象 User user = userService.findByUserName(principal); if(!ObjectUtils.isEmpty(user)){ //对象判空 return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), //这里生成随机字符串 在SaltUtils工具中生成 在myByteSource中运用 new MyByteSource(user.getSalt()), this.getName()); } return null; } }
ApplicationContextUtils.java
package com.demo.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class ApplicationContextUtils implements ApplicationContextAware { //对这个变量赋值以后 这个作为spring容器 private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } //拿到容器中已经实例化好的名字的类 根据名字获取类 //根据bean名字获取工厂中指定bean 对象 public static Object getBean(String beanName){ return context.getBean(beanName); } }
生成随机字符串,也就是常说的加盐的字符串,字符串处理
MyByteSource.java
package com.demo.shiro.salt; import java.io.File; import java.io.InputStream; import java.io.Serializable; import java.util.Arrays; import org.apache.shiro.codec.Base64; import org.apache.shiro.codec.CodecSupport; import org.apache.shiro.codec.Hex; import org.apache.shiro.util.ByteSource; //自定义salt实现 实现序列化接口 加密(加盐操作) public class MyByteSource implements ByteSource,Serializable { private byte[] bytes; private String cachedHex; private String cachedBase64; public MyByteSource(){ } public MyByteSource(byte[] bytes) { this.bytes = bytes; } public MyByteSource(char[] chars) { this.bytes = CodecSupport.toBytes(chars); } public MyByteSource(String string) { this.bytes = CodecSupport.toBytes(string); } public MyByteSource(ByteSource source) { this.bytes = source.getBytes(); } public MyByteSource(File file) { this.bytes = (new MyByteSource.BytesHelper()).getBytes(file); } public MyByteSource(InputStream stream) { this.bytes = (new MyByteSource.BytesHelper()).getBytes(stream); } public static boolean isCompatible(Object o) { return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream; } public byte[] getBytes() { return this.bytes; } public boolean isEmpty() { return this.bytes == null || this.bytes.length == 0; } public String toHex() { if (this.cachedHex == null) { this.cachedHex = Hex.encodeToString(this.getBytes()); } return this.cachedHex; } public String toBase64() { if (this.cachedBase64 == null) { this.cachedBase64 = Base64.encodeToString(this.getBytes()); } return this.cachedBase64; } public String toString() { return this.toBase64(); } public int hashCode() { return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0; } public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof ByteSource) { ByteSource bs = (ByteSource)o; return Arrays.equals(this.getBytes(), bs.getBytes()); } else { return false; } } private static final class BytesHelper extends CodecSupport { private BytesHelper() { } public byte[] getBytes(File file) { return this.toBytes(file); } public byte[] getBytes(InputStream stream) { return this.toBytes(stream); } } }
Salt.java,这里可以直接做运行测试,可以生成一个指定8位的随机字符串
package com.demo.utils; import java.util.Random; public class SaltUtils { /** * 生成salt的静态方法 * @param n 返回一个指定长度的盐 * @return */ public static String getSalt(int n){ char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { char aChar = chars[new Random().nextInt(chars.length)]; sb.append(aChar); } return sb.toString(); } public static void main(String[] args) { String salt = getSalt(8); System.out.println(salt); } }
前端页面
login.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>用户登录</h1> <form action="${pageContext.request.contextPath}/user/login" method="post"> 用户名:<input type="text" name="username" > <br/> 密码 : <input type="text" name="password"> <br> <input type="submit" value="登录"> </form> </body> </html>
index.jsp,授权器拿到
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>系统主页V1.0</h1> <h1><shiro:principal/></h1> <shiro:authenticated> 认证之后展示内容 <br> </shiro:authenticated> <shiro:notAuthenticated> 没有认证在之后展示内容 </shiro:notAuthenticated> <a href="${pageContext.request.contextPath}/user/logout">退出用户</a> <ul> <shiro:hasAnyRoles name="user,admin"> <li><a href="">用户管理</a> <ul> <shiro:hasPermission name="user:add:*"> <li><a href="">添加</a></li> </shiro:hasPermission> <shiro:hasPermission name="user:delete:*"> <li><a href="">删除</a></li> </shiro:hasPermission> <shiro:hasPermission name="user:update:*"> <li><a href="">修改</a></li> </shiro:hasPermission> <shiro:hasPermission name="order:find:*"> <li><a href="">查询</a></li> </shiro:hasPermission> </ul> </li> </shiro:hasAnyRoles> <shiro:hasRole name="admin"> <li><a href="">商品管理</a></li> <li><a href="">订单管理</a></li> <li><a href="">物流管理</a></li> </shiro:hasRole> </ul> </body> </html>