第三章:shiro集成spring 官方文档:https://shiro.apache.org/spring.html
数据库
参考附件《db_shiro.sql》
该数据库用户表(t_user)所有用户密码均为123456,加密的salt盐值为当前用户的用户名(username)
用户表(t_user)
角色表(t_role)
用户角色关系表(t_user_role)
权限表(t_permission)
角色权限关系表(t_role_permission)
ssm环境搭建 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 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 <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.7</maven.compiler.source > <maven.compiler.target > 1.7</maven.compiler.target > <spring.version > 5.0.2.RELEASE</spring.version > <slf4j.version > 1.6.6</slf4j.version > <log4j.version > 1.2.12</log4j.version > <mybatis.version > 3.4.5</mybatis.version > <shiro.version > 1.4.2</shiro.version > </properties > <dependencies > <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjweaver</artifactId > <version > 1.6.8</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aop</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context-support</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-orm</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-beans</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-test</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-tx</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > test</scope > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 3.1.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > javax.servlet.jsp</groupId > <artifactId > jsp-api</artifactId > <version > 2.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > jstl</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > ${log4j.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > ${slf4j.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > <version > ${slf4j.version}</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > ${mybatis.version}</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 1.3.0</version > </dependency > <dependency > <groupId > c3p0</groupId > <artifactId > c3p0</artifactId > <version > 0.9.1.2</version > <type > jar</type > <scope > compile</scope > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.1.2</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.15</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.54</version > </dependency > <dependency > <groupId > org.apache.shiro</groupId > <artifactId > shiro-core</artifactId > <version > ${shiro.version}</version > </dependency > <dependency > <groupId > org.apache.shiro</groupId > <artifactId > shiro-web</artifactId > <version > ${shiro.version}</version > </dependency > <dependency > <groupId > org.apache.shiro</groupId > <artifactId > shiro-spring</artifactId > <version > ${shiro.version}</version > </dependency > </dependencies >
需要在build标签加入以下代码
1 2 3 4 5 6 7 8 9 10 11 <resources > <resource > <directory > src/main/java</directory > <includes > <include > **/*.xml</include > <include > **/*.properties</include > </includes > <filtering > false</filtering > </resource > </resources >
applicationContext.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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:aop ="http://www.springframework.org/schema/aop" xmlns:tx ="http://www.springframework.org/schema/tx" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" > <context:component-scan base-package ="com.bdqn.service,com.bdqn.dao" /> <context:property-placeholder location ="classpath:database.properties" /> <bean id ="dataSource" class ="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name ="driverClass" value ="${jdbc.driver}" /> <property name ="jdbcUrl" value ="${jdbc.url}" /> <property name ="user" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" /> <property name ="configLocation" value ="classpath:mybatis-config.xml" > </property > <property name ="mapperLocations" > <list > <value > classpath:com/bdqn/dao/**/*.xml</value > </list > </property > <property name ="plugins" > <array > <bean class ="com.github.pagehelper.PageInterceptor" > <property name ="properties" > <props > <prop key ="helperDialect" > mysql</prop > <prop key ="reasonable" > true</prop > </props > </property > </bean > </array > </property > </bean > <bean id ="mapperScanner" class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="com.bdqn.dao" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:annotation-driven transaction-manager ="transactionManager" /> </beans >
spring mvc.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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:mvc ="http://www.springframework.org/schema/mvc" xmlns:context ="http://www.springframework.org/schema/context" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd " > <context:component-scan base-package ="com.bdqn.controller" /> <bean id ="viewResolver" class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > <mvc:resources mapping ="/statics/**" location ="/statics/" /> <mvc:annotation-driven > <mvc:message-converters register-defaults ="true" > <bean class ="org.springframework.http.converter.StringHttpMessageConverter" > <property name ="supportedMediaTypes" > <list > <value > text/html;charset=UTF-8</value > <value > application/json;charset=UTF-8</value > <value > text/plain;charset=UTF-8</value > <value > application/xml;charset=UTF-8</value > </list > </property > </bean > <bean class ="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter" > <property name ="supportedMediaTypes" > <list > <value > text/html;charset=UTF-8</value > <value > application/json;charset=UTF-8</value > <value > text/plain;charset=UTF-8</value > <value > application/xml;charset=UTF-8</value > </list > </property > </bean > </mvc:message-converters > </mvc:annotation-driven > <aop:aspectj-autoproxy proxy-target-class ="true" /> </beans >
mybatis.xml 1 2 3 4 5 6 7 8 9 10 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <typeAliases > <package name ="com.bdqn.entity" /> </typeAliases > </configuration >
web.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 52 53 54 55 56 57 58 59 60 61 62 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:applicationContext*.xml</param-value > </context-param > <servlet > <servlet-name > springmvc</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:spring-mvc.xml</param-value > </init-param > </servlet > <servlet-mapping > <servlet-name > springmvc</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <filter > <filter-name > encodingFilter</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter </filter-class > <init-param > <param-name > encoding</param-name > <param-value > UTF-8</param-value > </init-param > <init-param > <param-name > forceEncoding</param-name > <param-value > true</param-value > </init-param > </filter > <filter-mapping > <filter-name > encodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <welcome-file-list > <welcome-file > /login.jsp</welcome-file > </welcome-file-list > </web-app >
log4j.properties 1 2 3 4 5 log4j.rootCategory =debug, CONSOLE, LOGFILE log4j.logger.org.apache.axis.enterprise =FATAL, CONSOLE log4j.appender.CONSOLE =org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout =org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern =%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
database.properties 1 2 3 4 5 6 7 8 jdbc.driver =com.mysql.cj.jdbc.Driver jdbc.url =jdbc:mysql://localhost:3306/db_shiro?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai jdbc.username =root jdbc.password =root
login.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head > <title > 用户登录</title > </head > <body > <form action ="${pageContext.request.contextPath}/user/login" method ="post" > 用户名:<input type ="text" name ="username" /> <br /> 密码:<input type ="password" name ="userpwd" /> <br /> <input type ="submit" value ="登录" /> </form > </body > </html >
shiro集成spring 自定义Realm
在com.bdqn.realm包下创建UserRealm类
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 package com.bdqn.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;public class UserRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) { return null ; } @Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken authenticationToken) throws AuthenticationException { return null ; } }
applicationContext-shiro.xml
创建applicationContext-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 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="credentialsMatcher" class ="org.apache.shiro.authc.credential.HashedCredentialsMatcher" > <property name ="hashAlgorithmName" value ="md5" > </property > <property name ="hashIterations" value ="2" > </property > </bean > <bean id ="userRealm" class ="com.bdqn.realm.UserRealm" > <property name ="credentialsMatcher" ref ="credentialsMatcher" > </property > </bean > <bean id ="securityManager" class ="org.apache.shiro.web.mgt.DefaultWebSecurityManager" > <property name ="realm" ref ="userRealm" > </property > </bean > <bean id ="shiroFilter" class ="org.apache.shiro.spring.web.ShiroFilterFactoryBean" > <property name ="securityManager" ref ="securityManager" > </property > <property name ="loginUrl" value ="/login.jsp" > </property > <property name ="unauthorizedUrl" value ="/unauthorized.jsp" > </property > <property name ="filterChainDefinitions" > <value > /=anon /login.jsp=anon /user/login*=anon /logout=logout /**=authc </value > </property > </bean > </beans >
web.xml
修改web.xml文件,添加shiro与spring的整合配置
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 <filter > <filter-name > shiroFilter</filter-name > <filter-class > org.springframework.web.filter.DelegatingFilterProxy</filter-class > <init-param > <param-name > targetFilterLifecycle</param-name > <param-value > true</param-value > </init-param > <init-param > <param-name > targetBeanName</param-name > <param-value > shiroFilter</param-value > </init-param > </filter > <filter-mapping > <filter-name > shiroFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
使用shiro完成用户登录 实体类 User 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 package com.bdqn.entity;public class User { private Integer userid; private String username; private String userpwd; private String realname; public Integer getUserid () { return userid; } public void setUserid (Integer userid) { this .userid = userid; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getUserpwd () { return userpwd; } public void setUserpwd (String userpwd) { this .userpwd = userpwd; } public String getRealname () { return realname; } public void setRealname (String realname) { this .realname = realname; } }
Role 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 package com.bdqn.entity;public class Role { private Integer roleid; private String rolename; public Integer getRoleid () { return roleid; } public void setRoleid (Integer roleid) { this .roleid = roleid; } public String getRolename () { return rolename; } public void setRolename (String rolename) { this .rolename = rolename; } }
Permission 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 package com.bdqn.entity;public class Permission { private Integer permissionid; private String permissionname; private String permissioncode; public Integer getPermissionid () { return permissionid; } public void setPermissionid (Integer permissionid) { this .permissionid = permissionid; } public String getPermissionname () { return permissionname; } public void setPermissionname (String permissionname) { this .permissionname = permissionname; } public String getPermissioncode () { return permissioncode; } public void setPermissioncode (String permissioncode) { this .permissioncode = permissioncode; } }
UserMapper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.bdqn.dao;import com.bdqn.entity.User;public interface UserMapper { User findUserByUserName (String username) throws Exception ; }
UserMapper.xml 1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.bdqn.dao.UserMapper" > <select id ="findUserByUserName" resultType ="com.bdqn.entity.User" > select * from t_user where username = #{username} </select > </mapper >
UserService 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.bdqn.service;import com.bdqn.entity.User;public interface UserService { User findUserByUserName (String username) throws Exception ; }
UserServiceImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.bdqn.service.impl;import com.bdqn.dao.UserMapper;import com.bdqn.entity.User;import com.bdqn.service.UserService;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;@Service @Transactional public class UserServiceImpl implements UserService { @Resource private UserMapper userMapper; @Override public User findUserByUserName (String username) throws Exception { return userMapper.findUserByUserName(username); } }
LoginUserVo 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 package com.bdqn.vo;import com.bdqn.entity.User;import java.util.Set;public class LoginUserVo { private User user; private Set<String> roles; private Set<String> permissions; public User getUser () { return user; } public void setUser (User user) { this .user = user; } public Set<String> getRoles () { return roles; } public void setRoles (Set<String> roles) { this .roles = roles; } public Set<String> getPermissions () { return permissions; } public void setPermissions (Set<String> permissions) { this .permissions = permissions; } public LoginUserVo () { } public LoginUserVo (User user, Set<String> roles, Set<String> permissions) { this .user = user; this .roles = roles; this .permissions = permissions; } }
修改UserRealm 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 package com.bdqn.realm;import com.bdqn.entity.User;import com.bdqn.service.UserService;import com.bdqn.vo.LoginUserVo;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.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import javax.annotation.Resource;public class UserRealm extends AuthorizingRealm { @Resource private UserService userService; @Override public String getName () { return this .getClass().getSimpleName(); } @Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) { return null ; } @Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken authenticationToken) throws AuthenticationException { try { String username = authenticationToken.getPrincipal().toString(); User user= userService.findUserByUserName(username); if (user!=null ){ LoginUserVo loginUser = new LoginUserVo(user,null ,null ); ByteSource salt = ByteSource.Util.bytes(user.getUsername()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginUser,user.getUserpwd(),salt,getName()); return info; } } catch (Exception e) { e.printStackTrace(); } return null ; } }
UserController 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 package com.bdqn.controller;import com.bdqn.entity.User;import com.bdqn.vo.LoginUserVo;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpSession;@Controller @RequestMapping("/user") public class UserController { @PostMapping("/login") public String login (User user, HttpSession session) { Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getUserpwd()); try { subject.login(token); LoginUserVo loginUserVo = (LoginUserVo) subject.getPrincipal(); session.setAttribute("loginUser" ,loginUserVo.getUser()); return "main" ; } catch (AuthenticationException e) { e.printStackTrace(); } return "redirect:/login.jsp" ; } }
main.jsp
在WEB-INF/jsp/下添加main.jsp页面
1 2 3 4 5 6 7 8 9 10 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head > <title > 后台管理系统首页</title > </head > <body > <h1 style ="color: red" > shiro课程学习</h1 > <a href ="#" > 退出系统</a > </body > </html >
使用shiro完成授权 RoleMapper 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.bdqn.dao;import java.util.Set;public interface RoleMapper { Set<String> findRoleListByUserId (int userId) throws Exception ; }
RoleMapper.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.bdqn.dao.RoleMapper" > <select id ="findRoleListByUserId" resultType ="string" > SELECT r.rolename FROM t_role r INNER JOIN t_user_role ur ON ur.`roleid` = r.`roleid` WHERE ur.`userid` = #{userId} </select > </mapper >
RoleService 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.bdqn.service;import java.util.Set;public interface RoleService { Set<String> findRoleListByUserId (int userId) throws Exception ; }
RoleServiceImpl 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.bdqn.service.impl;import com.bdqn.dao.RoleMapper;import com.bdqn.service.RoleService;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.Set;@Service @Transactional public class RoleServiceImpl implements RoleService { @Resource private RoleMapper roleMapper; @Override public Set<String> findRoleListByUserId (int userId) throws Exception { return roleMapper.findRoleListByUserId(userId); } }
PermissionMapper 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.bdqn.dao;import java.util.Set;public interface PermissionMapper { Set<String> findPermissionListByUserId (int userId) throws Exception ; }
PermissionMapper.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.bdqn.dao.PermissionMapper" > <select id ="findPermissionListByUserId" resultType ="string" > SELECT p.permissioncode FROM t_permission p INNER JOIN t_role_permission rp ON rp.perid = p.permissionid INNER JOIN t_user_role ur ON ur.`roleid` = rp.roleid WHERE ur.`userid` = #{userId} </select > </mapper >
PermissionService 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.bdqn.service;import java.util.Set;public interface PermissionService { Set<String> findPermissionListByUserId (int userId) throws Exception ; }
PermissionServiceImpl 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.bdqn.service.impl;import com.bdqn.dao.PermissionMapper;import com.bdqn.service.PermissionService;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.Set;@Service @Transactional public class PermissionServiceImpl implements PermissionService { @Resource private PermissionMapper permissionMapper; @Override public Set<String> findPermissionListByUserId (int userId) throws Exception { return permissionMapper.findPermissionListByUserId(userId); } }
UserController 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 @ResponseBody @RequestMapping("/userAdd") public String userAdd () { return "userAdd" ; } @ResponseBody @RequestMapping("/userUpdate") public String userUpdate () { return "userUpdate" ; } @ResponseBody @RequestMapping("/userDelete") public String userDelete () { return "userDelete" ; } @ResponseBody @RequestMapping("/userQuery") public String userQuery () { return "userQuery" ; } @ResponseBody @RequestMapping("/userExport") public String userExport () { return "userExport" ; }
修改UserRealm 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 package com.bdqn.realm;import com.bdqn.entity.Permission;import com.bdqn.entity.Role;import com.bdqn.entity.User;import com.bdqn.service.PermissionService;import com.bdqn.service.RoleService;import com.bdqn.service.UserService;import com.bdqn.vo.LoginUserVo;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.apache.shiro.util.ByteSource;import javax.annotation.Resource;import java.util.Set;public class UserRealm extends AuthorizingRealm { @Resource private UserService userService; @Resource private RoleService roleService; @Resource private PermissionService permissionService; @Override public String getName () { return this .getClass().getSimpleName(); } @Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken token) throws AuthenticationException { try { String username = (String) token.getPrincipal(); User user = userService.findUserByUserName(username); if (user!=null ){ Set<String> roles = roleService.findRoleListByUserId(user.getUserid()); Set<String> permissions = permissionService.findPermissionListByUserId(user.getUserid()); LoginUserVo loginUserVo = new LoginUserVo(user,roles,permissions); ByteSource salt = ByteSource.Util.bytes(user.getUsername()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginUserVo, user.getUserpwd(),salt,this .getName()); return info; } } catch (Exception e) { e.printStackTrace(); } return null ; } @Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principals) { LoginUserVo loginUserVo = (LoginUserVo) principals.getPrimaryPrincipal(); Set<String> roles = loginUserVo.getRoles(); Set<String> permissions = loginUserVo.getPermissions(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); if (roles!=null && roles.size()>0 ){ info.setRoles(roles); } if (permissions!=null && permissions.size()>0 ){ info.setStringPermissions(permissions); } return info; } }
修改main.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 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <html > <head > <title > 后台管理系统首页</title > </head > <body > <h1 style ="color: red" > shiro课程学习</h1 > <shiro:hasPermission name ="user:query" > <a href ="/user/userQuery" > 查询用户</a > <br > </shiro:hasPermission > <shiro:hasPermission name ="user:add" > <a href ="/user/userAdd" > 添加用户</a > <br > </shiro:hasPermission > <shiro:hasPermission name ="user:update" > <a href ="/user/userDelete" > 删除用户</a > <br > </shiro:hasPermission > <shiro:hasPermission name ="user:delete" > <a href ="/user/userUpdate" > 修改用户</a > <br > </shiro:hasPermission > <shiro:hasPermission name ="user:export" > <a href ="/user/userExport" > 导出用户</a > <br > </shiro:hasPermission > <a href ="/logout" > 退出系统</a > </body > </html >
权限不足 修改applicationContex-shiro.xml文件
注入未授权页面
创建unauthorized.jsp
在根目录下新建此页面
1 2 3 4 5 6 7 8 9 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html > <head > <title > 权限不足</title > </head > <body > <h2 > 权限不足</h2 > </body > </html >
shiro注解式授权 常用注解介绍
@RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subject.isAuthenticated()返回 true
@RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
@RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
@RequiresRoles(value = {“admin”,”user”},logical = Logical.AND):表示当前Subject需要角色admin和user
@RequiresPermissions(value = {“user:delete”,”user:b”},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b
注解式授权配置
官方文档:https://shiro.apache.org/spring.html
使用注解式授权需要在spring配置文件中添加以下代码配置:
1 2 3 4 5 6 7 <bean id ="lifecycleBeanPostProcessor" class ="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <bean class ="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on ="lifecycleBeanPostProcessor" /> <bean class ="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" > <property name ="securityManager" ref ="securityManager" /> </bean >
注意:上述代码在applicationContext-shiro.xml文件中配置
注解式授权案例 EmployeeController
创建EmployeeController控制器,编写3个功能方法,分别是find(),add(),delete()
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 package com.bdqn.controller;import org.apache.shiro.authz.annotation.Logical;import org.apache.shiro.authz.annotation.RequiresPermissions;import org.apache.shiro.authz.annotation.RequiresRoles;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/employee") public class EmployeeController { @RequiresRoles(value = {"超级管理员"}) @RequestMapping("/find") public String find () { return "查询员工信息" ; } @RequiresRoles(value = {"超级管理员","经理"},logical = Logical.OR) @RequestMapping("/add") public String add () { return "添加员工信息" ; } @RequiresPermissions(value = {"user:delete"}) @RequestMapping("/delete") public String delete () { return "删除员工信息" ; } }
注意:权限注解可以是类级别或方法级别,上述用法是方法级别,用法与spring mvc的@RequestMapping注解类似
权限不足页面跳转配置
使用spring mvc提供的全局异常进行跳转,以下代码在applicationContext-shiro.xml文件中配置
在WEB-INF/jsp/下添加unauthorized.jsp页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <bean class ="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on ="lifecycleBeanPostProcessor" > <property name ="proxyTargetClass" value ="true" > </property > </bean > <bean id ="exceptionResolver" class ="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" > <property name ="exceptionMappings" > <props > <prop key ="org.apache.shiro.authz.UnauthorizedException" > unauthorized </prop > </props > </property > </bean >
全局异常配置(注解方式)
定义全局异常类,使用@ControllerAdvice注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.bdqn.exception;import org.apache.shiro.authz.UnauthorizedException;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;@ControllerAdvice public class GlobalExceptionHandlerAdvice { @ExceptionHandler(value= {UnauthorizedException.class}) public String unauthorized () { return "unauthorized" ; } }
在applicationContext.xml配置文件中扫描注解
1 <context:component-scan base-package ="com.bdqn.service,com.bdqn.dao,com.bdqn.exception" />
测试
分别登录不同角色的用户进行功能测试