pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--引入Jsp依赖--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!--jstl--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> |
在webapp文件夹中创建index.jsp和login.jsp
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="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> <ul> <li><a href="#">用户管理</a></li> <li><a href="#">商品管理</a></li> <li><a href="#">订单管理</a></li> <li><a href="#">物流管理</a></li> </ul> </body> </html> |
login.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="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> </html> |
application.properties
1 2 3 4 5 6 |
server.port=8080 server.servlet.context-path=/shiro spring.application.name=shiro spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp |
JSP 与IDEA 与SpringBoot存在一定的不兼容,修改此配置即可解决
pom.xml
1 2 3 4 5 6 |
<!--引入shrio--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.5.3</version> </dependency> |
在shiro文件夹下创建realm文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.test.shiro.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; /** * 自定义Realm */ public class CustomerRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { return null; } } |
在config文件夹中创建ShiroConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
@Configuration public class ShiroConfig { //ShiroFilter过滤所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //给ShiroFilter配置安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); //配置系统受限资源 //配置系统公共资源 Map<String, String> map = new HashMap<String, String>(); map.put("/index.jsp","authc");//表示这个资源需要认证和授权 // 设置认证界面路径 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //创建安全管理器 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } //创建自定义Realm @Bean public Realm getRealm() { CustomerRealm realm = new CustomerRealm(); return realm; } } |
输入http://localhost:8080/shiro/index.jsp,发现需要跳转到login.jsp
index.jsp
1 |
<a href="${pageContext.request.contextPath}/user/logout">退出登录</a> |
UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("logout") public String logout() { Subject subject = SecurityUtils.getSubject(); subject.logout(); return "redirect:/login.jsp"; } @RequestMapping("/login") public String login(String username, String password) { //获取主题对象 Subject subject = SecurityUtils.getSubject(); try { subject.login(new UsernamePasswordToken(username,password)); System.out.println("登录成功!!!"); return "redirect:/index.jsp"; } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户错误!!!"); } catch (IncorrectCredentialsException e) { System.out.println("密码错误!!!"); } return "redirect:/login.jsp"; } } |
CustomerRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * 自定义Realm */ public class CustomerRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String principal = (String) authenticationToken.getPrincipal(); if ("zhangsan".equals(principal)) { return new SimpleAuthenticationInfo(principal,"123456",this.getName()); } return null; } } |
ShiroConfig.java
公共资源一定是在受限资源上面,不然会造成死循环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@Configuration public class ShiroConfig { //ShiroFilter过滤所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //给ShiroFilter配置安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); //配置系统受限资源 //配置系统公共资源 Map<String, String> map = new HashMap<String, String>(); map.put("/user/login","anon");//表示这个为公共资源 一定是在受限资源上面 map.put("/**","authc");//表示这个受限资源需要认证和授权 // 设置认证界面路径 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //创建安全管理器 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } //创建自定义Realm @Bean public Realm getRealm() { CustomerRealm realm = new CustomerRealm(); return realm; } } |
登录正常,登出正常,未登录和登出后不能访问index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- 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=2 DEFAULT CHARSET=utf8; SET FOREIGN_KEY_CHECKS = 1; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!--引入mybatis--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.5</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency> |
application.properties
1 2 3 4 5 6 7 8 9 |
#配置数据源 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springboot_shrio?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=123456 mybatis.type-aliases-package=com.test.entity mybatis.mapper-locations=classpath:com/test/mapper/*.xml |
User.java
1 2 3 4 5 6 7 8 9 10 |
@Data @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor public class User { private String id; private String username; private String password; private String salt; } |
UserDao.java
1 2 3 4 5 6 7 |
@Mapper @Repository public interface UserDao { void save(User user); User findByUsername(String username); } |
UserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.test.dao.UserDao"> <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> </mapper> |
UserService.java
1 2 3 4 5 6 |
public interface UserService { //注册用户方法 void register(User user); //根据用户名查找用户 User findByUsername(String username); } |
SaltUtil.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class SaltUtil { public static String getSalt(int n) { char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { char c = chars[new Random().nextInt(chars.length)]; sb.append(c); } return sb.toString(); } public static void main(String[] args) { System.out.println(getSalt(4)); } } |
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void register(User user) { //1.获取随机盐 String salt = SaltUtil.getSalt(8); //2.将随机盐保存到数据 user.setSalt(salt); //3.明文密码进行md5 + salt + hash散列 Md5Hash MD5 = new Md5Hash(user.getPassword(),salt,1024); user.setPassword(MD5.toHex()); userDao.save(user); } @Override public User findByUsername(String username) { return userDao.findByUsername(username); } } |
UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
@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"; } @RequestMapping("/login") public String login(String username, String password) { //获取主题对象 Subject subject = SecurityUtils.getSubject(); try { subject.login(new UsernamePasswordToken(username,password)); System.out.println("登录成功!!!"); return "redirect:/index.jsp"; } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户错误!!!"); } catch (IncorrectCredentialsException e) { System.out.println("密码错误!!!"); } return "redirect:/login.jsp"; } } |
CustomerRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** * 自定义Realm */ public class CustomerRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String principal = (String) authenticationToken.getPrincipal(); //获取UserService对象 UserService userService = (UserService) ApplicationContextUtil.getBean("userService"); //System.out.println(userService); User user = userService.findByUsername(principal); if (!ObjectUtils.isEmpty(user)) { return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), this.getName()); } return null; } } |
ApplicationContextUtil.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Component public class ApplicationContextUtil implements ApplicationContextAware { 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); } } |
ShiroConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
@Configuration public class ShiroConfig { //ShiroFilter过滤所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //给ShiroFilter配置安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); //配置系统受限资源 //配置系统公共资源 Map<String, String> map = new HashMap<String, String>(); map.put("/user/login","anon");//表示这个为公共资源 一定是在受限资源上面 map.put("/user/register","anon");//表示这个为公共资源 一定是在受限资源上面 map.put("/register.jsp","anon");//表示这个为公共资源 一定是在受限资源上面 map.put("/**","authc");//表示这个受限资源需要认证和授权 // 设置认证界面路径 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //创建安全管理器 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } //创建自定义Realm @Bean public Realm getRealm() { CustomerRealm realm = new CustomerRealm(); HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //设置使用MD5加密算法 credentialsMatcher.setHashAlgorithmName("md5"); //散列次数 credentialsMatcher.setHashIterations(1024); realm.setCredentialsMatcher(credentialsMatcher); return realm; } |
register.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="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/register" method="post"> 用户名:<input type="text" name="username" > <br/> 密码 : <input type="text" name="password"> <br> <input type="submit" value="立即注册"> </form> </html> |
添加成功
认证
优化版推荐阅读(SpringBoot + Shiro + Jwt 实现登录认证,代码分析):https://blog.csdn.net/qq_43290318/article/details/108225519
CustomerRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String principal = (String) principalCollection.getPrimaryPrincipal(); if ("zhangsan".equals(principal)) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addRole("admin"); info.addRole("user"); info.addStringPermission("user:find:*"); info.addStringPermission("admin:*"); return info; } return null; } |
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="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>系统主页</h1> <a href="${pageContext.request.contextPath}/user/logout">退出登录</a> <ul> <shiro:hasRole name="user"> <li><a href="#">用户管理</a></li> <ul> <shiro:hasPermission name="user:save:*"> <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="user:find:*"> <li><a href="#">查询</a></li> </shiro:hasPermission> </ul> </shiro:hasRole> <shiro:hasRole name="admin"> <li><a href="#">商品管理</a></li> <li><a href="#">订单管理</a></li> <li><a href="#">物流管理</a></li> </shiro:hasRole> </ul> </body> </html> |
OrderController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Controller @RequestMapping("order") public class OrderController { @RequestMapping("save") public String save() { //基于角色 //获取主体对象 Subject subject = SecurityUtils.getSubject(); //代码方式 if (subject.hasRole("admin")) { System.out.println("保存订单!"); }else{ System.out.println("无权访问!"); } System.out.println("进入save方法============"); return "redircet:/index.jsp"; } } |
OrderController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Controller @RequestMapping("order") public class OrderController { @RequiresRoles(value={"admin","user"})//用来判断角色 同时具有 admin user @RequiresPermissions("user:update:01") //用来判断权限字符串 @RequestMapping("save") public String save(){ System.out.println("进入方法"); return "redirect:/index.jsp"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_perms -- ---------------------------- DROP TABLE IF EXISTS `t_perms`; CREATE TABLE `t_pers` ( `id` int(6) NOT NULL AUTO_INCREMENT, `name` varchar(80) DEFAULT NULL, `url` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- 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 DEFAULT CHARSET=utf8; -- ---------------------------- -- 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; -- ---------------------------- -- 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=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- 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; SET FOREIGN_KEY_CHECKS = 1; |
User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@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; } |
Role
1 2 3 4 5 6 7 8 9 10 11 12 |
@Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class Role implements Serializable { private String id; private String name; //定义权限的集合 private List<Perms> perms; } |
Perms
1 2 3 4 5 6 7 8 9 |
@Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class Perms implements Serializable { private String id; private String name; private String url; } |
UserDao.java
1 2 |
//根据用户名查询所有角色 User findRolesByUserName(String username); |
UserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<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> |
UserService.java
1 2 3 |
public interface UserService { User findRoleByUsername(String username); } |
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 |
@Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User findRoleByUsername(String username) { return userDao.findRoleByUsername(username); } } |
CustomerRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/** * 自定义Realm */ public class CustomerRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String principal = (String) principalCollection.getPrimaryPrincipal(); //获取UserService对象 UserService userService = (UserService) ApplicationContextUtil.getBean("userService"); //System.out.println(userService); //基于角色授权 User user = userService.findRoleByUsername(principal); if (!CollectionUtils.isEmpty(user.getRoles())) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); user.getRoles().forEach(role -> info.addRole(role.getName())); return info; } return null; } ...... } |
UserDao.java
1 2 3 4 5 6 7 8 |
@Mapper @Repository public interface UserDao { //根据角色id查询权限集合 Role findPermByRoleId(String id); //根据角色id查询权限集合 List<Perms> findPermsByRoleId2(String id); } |
UserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.test.dao.UserDao"> <resultMap id="roleMap" type="Role"> <result column="name" property="name"/> <collection property="perms" javaType="list" ofType="Perms"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="url" property="url"/> </collection> </resultMap> <select id="findPermByRoleId" parameterType="String" resultType="Role" resultMap="roleMap"> SELECT r.`name`,p.`id`,p.`name`,p.`url` FROM t_role r LEFT JOIN t_role_perms rp ON r.`id` = rp.`roleid` LEFT JOIN t_pers p ON rp.`permsid` = p.`id` WHERE r.`id` = #{id} </select> <select id="findPermsByRoleId2" 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_pers p ON rp.permsid=p.id WHERE r.id=#{id} </select> </mapper> |
UserService.java
1 2 3 4 5 6 |
public interface UserService { //根据角色id查询权限集合 Role findPermByRoleId(String id); //根据角色id查询权限集合 List<Perms> findPermsByRoleId2(String id); } |
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public Role findPermByRoleId(String id) { return userDao.findPermByRoleId(id); } @Override public List<Perms> findPermsByRoleId2(String id) { return userDao.findPermsByRoleId2(id); } } |
CustomerRealm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/** * 自定义Realm */ public class CustomerRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String principal = (String) principalCollection.getPrimaryPrincipal(); //获取UserService对象 UserService userService = (UserService) ApplicationContextUtil.getBean("userService"); //System.out.println(userService); //基于角色授权 User user = userService.findRoleByUsername(principal); System.out.println("user======="+user); if (!CollectionUtils.isEmpty(user.getRoles())) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); user.getRoles().forEach(role ->{ info.addRole(role.getName()); /*Role role2 = userService.findPermByRoleId(role.getId()); System.out.println("role2======"+role2); if (!CollectionUtils.isEmpty(role2.getPerms())) { role2.getPerms().forEach(perm -> info.addStringPermission(perm.getName())); }*/ //权限信息 List<Perms> perms = userService.findPermsByRoleId2(role.getId()); System.out.println("perms========"+perms); if(!CollectionUtils.isEmpty(perms) && perms.get(0)!=null ){ perms.forEach(perm->{ info.addStringPermission(perm.getName()); }); } }); return info; } return null; } ...... } |
Cache 缓存: 计算机内存中一段数据
作用: 用来减轻DB的访问压力,从而提高系统的查询效率
流程:
1 2 3 4 5 6 |
<!--引入shiro和ehcache--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.5.3</version> </dependency> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//3.创建自定义realm @Bean public Realm getRealm() { CustomerRealm realm = new CustomerRealm(); HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //设置使用MD5加密算法 credentialsMatcher.setHashAlgorithmName("md5"); //散列次数 credentialsMatcher.setHashIterations(1024); realm.setCredentialsMatcher(credentialsMatcher); //开启缓存管理器 realm.setCacheManager(new EhCacheManager()); realm.setCachingEnabled(true);//开启缓存 realm.setAuthenticationCachingEnabled(true);//开启认证缓存 realm.setAuthenticationCacheName("authentication"); realm.setAuthorizationCachingEnabled(true);//开启授权缓存 realm.setAuthorizationCacheName("authorization"); return realm; } |
注意:如果控制台没有任何sql展示说明缓存已经开启
1 2 3 4 5 |
<!--redis整合springboot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> |
1 2 3 |
spring.redis.port=6379 spring.redis.host=localhost spring.redis.database=0 |
自定义shiro缓存管理器
RedisCacheManager.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; //自定义shiro缓存管理器 public class RedisCacheManager implements CacheManager { //参数1:认证或者是授权缓存的统一名称 @Override public <K, V> Cache<K, V> getCache(String cacheName) throws CacheException { System.out.println(cacheName); return new RedisCache<K,V>(cacheName); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
//自定义redis缓存的实现 public class RedisCache<k,v> implements Cache<k,v> { private String cacheName; public RedisCache() { } public RedisCache(String cacheName) { this.cacheName = cacheName; } @Override public v get(k k) throws CacheException { return (v) getRedisTemplate().opsForHash().get(this.cacheName, k.toString()); } @Override public v put(k k, v v) throws CacheException { System.out.println("put key: "+k); System.out.println("put value:"+v); getRedisTemplate().opsForHash().put(this.cacheName,k.toString(), v); return null; } @Override public v remove(k k) throws CacheException { System.out.println("=============remove============="); return (v) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString()); } @Override public void clear() throws CacheException { System.out.println("=============clear=============="); getRedisTemplate().delete(this.cacheName); } @Override public int size() { return getRedisTemplate().opsForHash().size(this.cacheName).intValue(); } @Override public Set<k> keys() { return getRedisTemplate().opsForHash().keys(this.cacheName); } @Override public Collection<v> values() { return getRedisTemplate().opsForHash().values(this.cacheName); } private RedisTemplate getRedisTemplate(){ RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate"); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); return redisTemplate; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
import org.apache.shiro.codec.Base64; import org.apache.shiro.codec.CodecSupport; import org.apache.shiro.codec.Hex; import org.apache.shiro.util.ByteSource; import java.io.File; import java.io.InputStream; import java.io.Serializable; import java.util.Arrays; //自定义salt实现 实现序列化接口 public class MyByteSource implements ByteSource, Serializable { private byte[] bytes; private String cachedHex; private String cachedBase64; 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); } } } |
修改自定义realm中使用的salt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span class="token annotation punctuation">@Override</span> <span class="token keyword">protected</span> <span class="token class-name">AuthenticationInfo</span> <span class="token function">doGetAuthenticationInfo</span><span class="token punctuation">(</span><span class="token class-name">AuthenticationToken</span> authenticationToken<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">AuthenticationException</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">String</span> principal <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">)</span> authenticationToken<span class="token punctuation">.</span><span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取UserService对象</span> <span class="token class-name">UserService</span> userService <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">UserService</span><span class="token punctuation">)</span> <span class="token class-name">ApplicationContextUtil</span><span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"userService"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//System.out.println(userService);</span> <span class="token class-name">User</span> user <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">findByUsername</span><span class="token punctuation">(</span>principal<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token class-name">ObjectUtils</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">SimpleAuthenticationInfo</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span><span class="token function">getUsername</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MyByteSource</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span><span class="token function">getSalt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.Random; /** *@创建人 cx *@创建时间 2018/11/27 17:36 *@描述 验证码生成 */ public class VerifyCodeUtils{ //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; private static Random random = new Random(); /** * 使用系统默认字符源生成验证码 * @param verifySize 验证码长度 * @return */ public static String generateVerifyCode(int verifySize){ return generateVerifyCode(verifySize, VERIFY_CODES); } /** * 使用指定源生成验证码 * @param verifySize 验证码长度 * @param sources 验证码字符源 * @return */ public static String generateVerifyCode(int verifySize, String sources){ if(sources == null || sources.length() == 0){ sources = VERIFY_CODES; } int codesLen = sources.length(); Random rand = new Random(System.currentTimeMillis()); StringBuilder verifyCode = new StringBuilder(verifySize); for(int i = 0; i < verifySize; i++){ verifyCode.append(sources.charAt(rand.nextInt(codesLen-1))); } return verifyCode.toString(); } /** * 生成随机验证码文件,并返回验证码值 * @param w * @param h * @param outputFile * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{ String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, outputFile, verifyCode); return verifyCode; } /** * 输出随机验证码图片流,并返回验证码值 * @param w * @param h * @param os * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{ String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, os, verifyCode); return verifyCode; } /** * 生成指定验证码图像文件 * @param w * @param h * @param outputFile * @param code * @throws IOException */ public static void outputImage(int w, int h, File outputFile, String code) throws IOException{ if(outputFile == null){ return; } File dir = outputFile.getParentFile(); if(!dir.exists()){ dir.mkdirs(); } try{ outputFile.createNewFile(); FileOutputStream fos = new FileOutputStream(outputFile); outputImage(w, h, fos, code); fos.close(); } catch(IOException e){ throw e; } } /** * 输出指定验证码图片流 * @param w * @param h * @param os * @param code * @throws IOException */ public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{ int verifySize = code.length(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Random rand = new Random(); Graphics2D g2 = image.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); Color[] colors = new Color[5]; Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW }; float[] fractions = new float[colors.length]; for(int i = 0; i < colors.length; i++){ colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; fractions[i] = rand.nextFloat(); } Arrays.sort(fractions); g2.setColor(Color.GRAY);// 设置边框色 g2.fillRect(0, 0, w, h); Color c = getRandColor(200, 250); g2.setColor(c);// 设置背景色 g2.fillRect(0, 2, w, h-4); //绘制干扰线 Random random = new Random(); g2.setColor(getRandColor(160, 200));// 设置线条的颜色 for (int i = 0; i < 20; i++) { int x = random.nextInt(w - 1); int y = random.nextInt(h - 1); int xl = random.nextInt(6) + 1; int yl = random.nextInt(12) + 1; g2.drawLine(x, y, x + xl + 40, y + yl + 20); } // 添加噪点 float yawpRate = 0.05f;// 噪声率 int area = (int) (yawpRate * w * h); for (int i = 0; i < area; i++) { int x = random.nextInt(w); int y = random.nextInt(h); int rgb = getRandomIntColor(); image.setRGB(x, y, rgb); } shear(g2, w, h, c);// 使图片扭曲 g2.setColor(getRandColor(100, 160)); int fontSize = h-4; Font font = new Font("Algerian", Font.ITALIC, fontSize); g2.setFont(font); char[] chars = code.toCharArray(); for(int i = 0; i < verifySize; i++){ AffineTransform affine = new AffineTransform(); affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2); g2.setTransform(affine); g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10); } g2.dispose(); ImageIO.write(image, "jpg", os); } private static Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } private static int getRandomIntColor() { int[] rgb = getRandomRgb(); int color = 0; for (int c : rgb) { color = color << 8; color = color | c; } return color; } private static int[] getRandomRgb() { int[] rgb = new int[3]; for (int i = 0; i < 3; i++) { rgb[i] = random.nextInt(255); } return rgb; } private static void shear(Graphics g, int w1, int h1, Color color) { shearX(g, w1, h1, color); shearY(g, w1, h1, color); } private static void shearX(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(2); boolean borderGap = true; int frames = 1; int phase = random.nextInt(2); for (int i = 0; i < h1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(0, i, w1, 1, (int) d, 0); if (borderGap) { g.setColor(color); g.drawLine((int) d, i, 0, i); g.drawLine((int) d + w1, i, w1, i); } } } private static void shearY(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(40) + 10; // 50; boolean borderGap = true; int frames = 20; int phase = 7; for (int i = 0; i < w1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(i, 0, 1, h1, 0, (int) d); if (borderGap) { g.setColor(color); g.drawLine(i, (int) d, i, 0); g.drawLine(i, (int) d + h1, i, h1); } } } public static void main(String[] args) throws IOException { //获取验证码 String s = generateVerifyCode(4); //将验证码放入图片中 outputImage(260,60,new File("/Users/chenyannan/Desktop/安工资料/aa.jpg"),s); System.out.println(s); } } |
1 2 3 4 5 6 |
<form action="${pageContext.request.contextPath}/user/login" method="post"> 用户名:<input type="text" name="username"> <br/> 密码 : <input type="text" name="password"> <br/> 请输入验证码: <input type="text" name="code"><img src="${pageContext.request.contextPath}/user/getImage" alt=""><br/> <input type="submit" value="登录"> </form> |
1 2 3 4 5 6 7 8 9 10 11 |
@RequestMapping("getImage") public void getImage(HttpSession session, HttpServletResponse response) throws IOException { //生成验证码 String code = VerifyCodeUtils.generateVerifyCode(4); //验证码放入session session.setAttribute("code",code); //验证码存入图片 ServletOutputStream os = response.getOutputStream(); response.setContentType("image/png"); VerifyCodeUtils.outputImage(220,60,os,code); } |
ShiroConfig.java
1 |
map.put("/user/getImage","anon");//验证码 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@RequestMapping("login") public String login(String username, String password,String code,HttpSession session) { //比较验证码 String codes = (String) session.getAttribute("code"); try { if (codes.equalsIgnoreCase(code)){ //获取主体对象 Subject subject = SecurityUtils.getSubject(); subject.login(new UsernamePasswordToken(username, password)); return "redirect:/index.jsp"; }else{ throw new RuntimeException("验证码错误!"); } } 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"; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
需要在jsp页面中引入标签 <%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %> 标签: <shiro:authenticated> 登录之后 <shiro:notAuthenticated> 不在登录状态时 <shiro:guest> 用户在没有RememberMe时 <shiro:user> 用户在RememberMe时 <shiro:hasAnyRoles name="abc,123" > 在有abc或者123角色时 <shiro:hasRole name="abc"> 拥有角色abc <shiro:lacksRole name="abc"> 没有角色abc <shiro:hasPermission name="abc"> 拥有权限资源abc <shiro:lacksPermission name="abc"> 没有abc权限资源 <shiro:principal> 显示用户身份名称 <shiro:principal property="username"/> 显示用户身份中的属性值 |
1 2 3 4 5 |
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency> |
1 2 |
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<!-- 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。 --> <p shiro:guest="">Please <a href="login.html">login</a></p> <!-- 认证通过或已记住的用户。 --> <p shiro:user=""> Welcome back John! Not John? Click <a href="login.html">here</a> to login. </p> <!-- 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。 --> <p shiro:authenticated=""> Hello, <span shiro:principal=""></span>, how are you today? </p> <a shiro:authenticated="" href="updateAccount.html">Update your contact information</a> <!-- 输出当前用户信息,通常为登录帐号信息。 --> <p>Hello, <shiro:principal/>, how are you today?</p> <!-- 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。 --> <p shiro:notAuthenticated=""> Please <a href="login.html">login</a> in order to update your credit card information. </p> <!-- 验证当前用户是否属于该角色。 --> <a shiro:hasRole="admin" href="admin.html">Administer the system</a><!-- 拥有该角色 --> <!-- 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。 --> <p shiro:lacksRole="developer"><!-- 没有该角色 --> Sorry, you are not allowed to developer the system. </p> <!-- 验证当前用户是否属于以下所有角色。 --> <p shiro:hasAllRoles="developer, 2"><!-- 角色与判断 --> You are a developer and a admin. </p> <!-- 验证当前用户是否属于以下任意一个角色。 --> <p shiro:hasAnyRoles="admin, vip, developer,1"><!-- 角色或判断 --> You are a admin, vip, or developer. </p> <!--验证当前用户是否拥有指定权限。 --> <a shiro:hasPermission="userInfo:add" href="createUser.html">添加用户</a><!-- 拥有权限 --> <!-- 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。 --> <p shiro:lacksPermission="userInfo:del"><!-- 没有权限 --> Sorry, you are not allowed to delete user accounts. </p> <!-- 验证当前用户是否拥有以下所有角色。 --> <p shiro:hasAllPermissions="userInfo:view, userInfo:add"><!-- 权限与判断 --> You can see or add users. </p> <!-- 验证当前用户是否拥有以下任意一个权限。 --> <p shiro:hasAnyPermissions="userInfo:view, userInfo:del"><!-- 权限或判断 --> You can see or delete users. </p> <a shiro:hasPermission="pp" href="createUser.html">Create a new User</a> |
1 2 3 4 |
@Bean(name = "shiroDialect") public ShiroDialect shiroDialect(){ return new ShiroDialect(); } |
内容参考:
B站编程不良人:https://www.bilibili.com/video/BV1uz4y197Zm
仅用于学习!
from:https://blog.csdn.net/Yearingforthefuture/article/details/117384035