基于springboot-2.1.4构建,packaging选择war方式
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.tingcream</groupId> <artifactId>springshiro</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>springshiro</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 引入jsp 、jstl支持 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- 配置aop支持的方式二 spring的织入 aspects cglib --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.2.0</version> </dependency> <!-- jdbc starter引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 引入druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!-- 引入mybatis的starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!-- redis的starter引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- shiro spring 引入 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <target>1.8</target> <source>1.8</source> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build> </project>
1、pom.xml中shiro-spring-1.4.0会自动引入shiro-web-1.4.0.jar,shiro-web-1.4.0.jar会自动引入shiro-core-1.4.0jar。故这里整合时,shiro的依赖包我们只需要引入一个shiro-spring-1.4.0jar即可。
2、shiro-core-1.4.0的权限注解如RequireRoles,可以标记到Controller类上,而1.3.2版本中权限注解标记到Controller类上无效。
#服务器配置 server: port: 8082 context-path: / spring: #devtools配置 devtools: restart: exclude: static/** application: name: springshiro2 #jsp视图 mvc: view: prefix: /WEB-INF/pages #suffix: .jsp #数据库连接池 datasource: druid: driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 url: jdbc:mysql://localhost:3306/springshiro?useUnicode=true&characterEncoding=utf-8&useSSL=false initial-size: 5 #初始化连接数 max-active: 10 #最大活跃连接数 min-idle: 5 #最小空闲连接数 max-wait: 60000 #最大连接等待时间 毫秒 remove-abandoned: true #超过时间限制是否回收 removeAbandonedTimeout: 1800 #超时丢弃连接 1800秒即30分钟 timeBetweenEvictionRunsMillis: 60000 #配置时间间隔进行一次检测,毫秒 validationQuery: SELECT 1 FROM DUAL #用来检测连接是否有效的sql,要求是一个查询语句 testWhileIdle: true #申请连接的时候检测 testOnBorrow: false testOnReturn: false poolPreparedStatements: true #打开PSCache,并且指定每个连接上PSCache的大小 maxPoolPreparedStatementPerConnectionSize: 20 maxOpenPreparedStatements: 20 #redis连接池 redis: host: 192.168.11.10 port: 6379 password: 123456 ssl: false database: 1 timeout: 6000 jedis: pool: max-active: 8 #缺省值8 max-idle: 8 #缺省值8 min-idle: 0 #缺省值0 max-wait: 3000 #缺省值-1 mybatis: config-location: classpath:SqlMapConfig.xml #日志 logging: level: root: INFO org.springframework.web: INFO org.springframework.jdbc: DEBUG com.tingcream.springshiro2: DEBUG file: e:/log/springshiro/springshiro2.log
<?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> <settings> <!-- 启动延迟加载 积极加载false --> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings> <typeAliases> <!-- <package name="com.tingcream.springmybatis.model"/> --> <!-- 配置实体bean包及其子包,别名为类名的简单名称,首字母大小写均可。如Student或student均可 --> <package name="com.tingcream.springshiro2"/> </typeAliases> <mappers> <!--配置mapper接口和mapper.xml所在包(包含子包)--> <package name="com.tingcream.springshiro2"/> </mappers> </configuration>
package com.tingcream.springshiro2; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true) @MapperScan(basePackages= {"com.tingcream.springshiro2"})//可多个,含子包,支持通配符 public class Springshiro2Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(Springshiro2Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Springshiro2Application.class); } }
package com.tingcream.springshiro2.configuration; import java.io.Serializable; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import com.tingcream.springshiro2.common.redis.RedisHelper; @Configuration public class RedisConfig { @SuppressWarnings({ "unchecked", "rawtypes" }) @Bean public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate redisTemplate = new RedisTemplate(); StringRedisSerializer keySerializer = new StringRedisSerializer(); GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(keySerializer);//键 redisTemplate.setHashKeySerializer(keySerializer);//键 redisTemplate.setValueSerializer(valueSerializer);//值 redisTemplate.setHashValueSerializer(valueSerializer);//值 return redisTemplate; } @Bean public RedisHelper redisHelper(RedisTemplate<Serializable, Object> redisTemplate) { RedisHelper redisHelper = new RedisHelper(); redisHelper.setRedisTemplate(redisTemplate); return redisHelper; } }
package com.tingcream.springshiro2.common.redis; import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; /** * redis 辅助工具类 * @author jelly */ public class RedisHelper { private RedisTemplate<Serializable, Object> redisTemplate; public void setRedisTemplate( RedisTemplate<Serializable, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public RedisTemplate<Serializable, Object> getRedisTemplate() { return redisTemplate; } /** * hash set * @param key * @param field * @param value */ public void hset(String key ,String field,Object value){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); hashOperation.put(field, value); } /** * hash set with ttlSec * @param key * @param field * @param value * @param ttl */ public void hset(String key ,String field,Object value,long ttl){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); hashOperation.put(field, value); redisTemplate.expire(key, ttl, TimeUnit.SECONDS); } /** * hash get * @param key * @param field * @return */ public Object hget(String key,String field){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); return hashOperation.get(field); } /** * hash hdel field * @param key * @param field */ public void hdel(String key,Object field){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); hashOperation.delete(field); } /** * hash hdel field1 field2 * @param key * @param fields */ public void hdel(final String key,final Object... fields){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); hashOperation.delete(fields); } /** * hash hlen * @param key * @return */ public Long hlen(String key){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); return hashOperation.size(); } /** * hash hkeys * @author jelly * @param key * @return */ public Set<String> hkeys(String key){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); return hashOperation.keys(); } /** * hash hvals * @param key * @return */ public List<Object> hvals(String key){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); return hashOperation.values(); } /** * hash hgetall * @param key * @return */ public Map<String,Object> hgetall(String key){ BoundHashOperations<Serializable, String, Object> hashOperation= redisTemplate.boundHashOps(key); return hashOperation.entries(); } /** * 传入 多个key * key1 key2 key3 */ public void remove(final String... keys) { for (String key : keys) { remove(key); } } /** * 批量删除key 根据匹配的parttern * 如 mylist* 能匹配 mylist1 mylist2 */ public void removePattern(final String pattern) { Set<Serializable> keys = redisTemplate.keys(pattern); if (keys.size() > 0) { redisTemplate.delete(keys); } } /** * 删除key-Object 根据传入的key */ public void remove(final String key) { redisTemplate.delete(key); } /** * 判断缓存中是否存在 指定的key */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 读取缓存 * @param key * @return */ public Object get(final String key) { Object result = null; ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); result = operations.get(key); return result; } /** * set * @author jelly * @param key * @param value */ public void set(final String key, Object value) { try { ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); operations.set(key, value); } catch (Exception e) { e.printStackTrace(); } } /** * set * @param key * @param value * @param ttl */ public void set(final String key, Object value, Long ttl) { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value, ttl, TimeUnit.SECONDS) ; redisTemplate.expire(key, ttl, TimeUnit.SECONDS);// } public boolean expireKey(final String key, Long ttl){ return redisTemplate.expire(key, ttl, TimeUnit.SECONDS); } /** * 清空redis当前db */ public void flushDB(){ redisTemplate.execute(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { try { connection.flushDb(); return ""; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }); } /** * 清空redis所有 db */ public void flushAll(){ redisTemplate.execute(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { try { connection.flushAll(); return ""; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }); } }
<!-- shiro spring 引入 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
package com.tingcream.springshiro2.configuration; import java.util.HashMap; import java.util.Map; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.web.filter.DelegatingFilterProxy; import com.tingcream.springshiro2.shiro.MyRealm; /** * shiro 配置类 * @author jelly */ @Configuration public class ShiroConfig { @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean @DependsOn({ "lifecycleBeanPostProcessor" }) public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator(); autoProxyCreator.setProxyTargetClass(true);//aop切入 return autoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } //将自己的验证方式加入容器 @Bean public MyRealm myRealm() { return new MyRealm(); } //配置shiro session 的一个管理器 @Bean(name = "sessionManager") public DefaultWebSessionManager sessionManager(){ DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); // 设置session过期时间 sessionManager.setGlobalSessionTimeout(30*60*1000); return sessionManager; } @Bean(name = "securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm( myRealm() ); defaultWebSecurityManager.setSessionManager( sessionManager() ); return defaultWebSecurityManager; } @Bean public FilterRegistrationBean<DelegatingFilterProxy> delegatingFilterProxy(){ FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean = new FilterRegistrationBean<DelegatingFilterProxy>(); DelegatingFilterProxy proxy = new DelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName("shiroFilter"); filterRegistrationBean.setFilter(proxy); filterRegistrationBean.setOrder(1); //filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } //Filter工厂,设置对应的过滤条件和跳转条件 @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean filterBean =new ShiroFilterFactoryBean(); filterBean.setSecurityManager(securityManager());//shiro的核心安全接口,这个属性是必须的 filterBean.setLoginUrl("/login");//身份认证失败,跳转到登陆页面url filterBean.setSuccessUrl("/home");//登录成功 跳转的页面url filterBean.setUnauthorizedUrl("/unauthorized");//权限验证失败,跳转到指定页面url //Map<String, Filter> filters=new HashMap<String,Filter>(); //filterBean.setFilters(filters); Map<String,String> filterChainDefinitionMap =new HashMap<String,String>(); filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/logout", "logout"); // filterChainDefinitionMap.put("/student/**", "roles[student]"); // filterChainDefinitionMap.put("/teacher/**", "roles[teacher]"); filterChainDefinitionMap.put("/**", "authc"); filterBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return filterBean ; } }
package com.tingcream.springshiro2.shiro; import java.util.Set; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import com.tingcream.springshiro2.user.model.User; import com.tingcream.springshiro2.user.service.LoginService; /** * 自定义 realm */ public class MyRealm extends AuthorizingRealm { @Autowired private LoginService loginService ; @Override public String getName() { return "myRealm"; } /** * 对当前subject进行身份认证 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("访问了doGetAuthenticationInfo认证方法"); String username=(String)token.getPrincipal(); User user =loginService.findUserByUsername(username); if(user==null) { //登陆失败 return null; } AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName()); return authcInfo; } /** * 对当前subject进行权限认证(授权) * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("访问了doGetAuthorizationInfo授权方法"); String username=(String)principals.getPrimaryPrincipal(); SecurityUtils.getSubject().getSession(); SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo(); Set<String> roleNames=loginService.findUserRoleNames(username); Set<String> permNames=loginService.findUserPermNames(username); authorizationInfo.setRoles(roleNames); authorizationInfo.setStringPermissions(permNames); return authorizationInfo; } }
package com.tingcream.springshiro2.common.exception; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.shiro.authz.UnauthorizedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.tingcream.springshiro2.common.ret.RetMsg; @ControllerAdvice public class GlobalExceptionHandler { private Logger logger =LoggerFactory.getLogger(this.getClass()); @ResponseBody @ExceptionHandler(BindException.class) public RetMsg handleBindException(BindException e,HttpServletRequest request) { logger.error(e.getMessage(),e);//记录完整错误信息 Map<String,String> map=new HashMap<String,String>(); List<ObjectError> errors = e.getBindingResult().getAllErrors(); errors.stream().forEach((ObjectError err)->{ String field= ((FieldError)err).getField(); String msg =err.getDefaultMessage(); map.put(field,msg); }); return new RetMsg(999, "请求参数验证失败", map); } // /** // * shiro 授权验证不通过 // * @return // */ // @ResponseBody // @ExceptionHandler(value=UnauthorizedException.class) // public RetMsg handleUnauthorizedException(UnauthorizedException e,HttpServletRequest request) { // logger.error(e.getMessage(),e); // System.out.println("shiro授权验证不通过"); // return RetMsg.success("抱歉,授权验证不通过,您无法访问此资源"); // } /** * shiro 授权验证不通过 * @return */ @ExceptionHandler(value=UnauthorizedException.class) public ModelAndView handleUnauthorizedException(UnauthorizedException e,HttpServletRequest request) { logger.error(e.getMessage(),e); System.out.println("shiro授权验证不通过"); return new ModelAndView("/unauthorized.jsp");//返回jsp视图 } }
package com.tingcream.springshiro2.user.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; 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 org.springframework.web.bind.annotation.RequestMethod; import com.tingcream.springshiro2.common.constant.GlobalConstant; import com.tingcream.springshiro2.user.model.User; import com.tingcream.springshiro2.user.service.LoginService; @Controller public class LoginController { @Autowired private LoginService loginService; @RequestMapping(value="/home",method=RequestMethod.GET) public String index(HttpServletRequest request,HttpServletResponse response) { Subject subject = SecurityUtils.getSubject(); String username= (String) subject.getPrincipal(); // HttpSession session = WebUtils.toHttp(request).getSession(); org.apache.shiro.session.Session session = subject.getSession(); User sessionUser =(User)session.getAttribute(GlobalConstant.SESSION_USER); if(sessionUser==null) { //根据用户名到数据库中查询 sessionUser=loginService.findUserByUsername(username); } session.setAttribute(GlobalConstant.SESSION_USER, sessionUser); return "/home.jsp"; } @RequestMapping(value="/login",method=RequestMethod.GET) public String login(HttpServletRequest request,HttpServletResponse response) { return "/login.jsp"; } @RequestMapping(value="/login",method=RequestMethod.POST) public String doLogin(HttpServletRequest request,HttpServletResponse response, String username,String password) { UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try{ //注意这一步 很重要 subject.login(token); //subject.getSession()和request.getSession()得到的session对象的用法基本一致 //subject.getSession().setAttribute("currentUser", user); subject.getSession().setAttribute("msg", "你好,您已登录成功!"); // return "forward:/home"; return "redirect:/home";//重定向到首页 }catch ( UnknownAccountException e ) { e.printStackTrace(); System.out.println("未知的账户,用户名不存在"); } catch ( IncorrectCredentialsException e ) { e.printStackTrace(); System.out.println("密码错误"); } catch ( LockedAccountException e ) { e.printStackTrace(); System.out.println("账户被锁定"); } catch ( ExcessiveAttemptsException e ) { e.printStackTrace(); System.out.println("过度的尝试"); }catch ( AuthenticationException e ) { e.printStackTrace(); System.out.println("认证失败"); }catch(Exception e) { e.printStackTrace(); } request.setAttribute("errMsg", "用户名或者密码错误"); return "/login.jsp"; } @RequestMapping("/unauthorized") public String unauthorized() { System.out.println("asdfasdfasdf"); return "/unauthorized.jsp"; } }
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Insert title here</title> </head> <body> <h1>home 首页 </h1> ${msg} ==== 欢迎您 :<shiro:principal /> <br/> 用户id: ${sessionUser.userId } <br/> 用户创建时间: ${sessionUser.createtime } </body> </html>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Insert title here</title> </head> <body> <h1>用户登录</h1> <form action="${pageContext.request.contextPath }/login" method="post"> username: <input type="text" name="username"/> <br/> password: <input type="password" name="password"/> <br/> <button type="submit">登录</button> ${errMsg} </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Insert title here</title> </head> <body> <h1>unauthorized</h1> <h3>抱歉,权限(role、perms)验证未通过</h3> </body> </html>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Insert title here</title> </head> <body> <h1>student.jsp页面</h1> </body> </html>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Insert title here</title> </head> <body> <h1>teacher.jsp页面</h1> </body> </html>
package com.tingcream.springshiro2.user.service; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.tingcream.springshiro2.common.constant.GlobalConstant; import com.tingcream.springshiro2.common.redis.RedisHelper; import com.tingcream.springshiro2.user.mapper.UserMapper; import com.tingcream.springshiro2.user.model.User; @Service //@Transactional public class LoginService { @Autowired private UserMapper userMapper ; @Autowired private RedisHelper redisHelper ; /** * 根据用户名查询用户实体 * @param username 用户名 * @return */ public User findUserByUsername(String username) { User user = (User) redisHelper.hget(GlobalConstant.CACHE_USER, username); if(user==null) { user= userMapper.findUserByUsername(username); redisHelper.hset(GlobalConstant.CACHE_USER, username, user); } return user; } /** * 根据用户id查询用户所有的角色名称 * @param username 用户名 * @return */ @SuppressWarnings("unchecked") public Set<String> findUserRoleNames(String username ){ Set<String> names= (Set<String>) redisHelper.hget(GlobalConstant.CACHE_USER_ROLENAMES,username); if(names==null) { names=userMapper.findUserRoleNames(username); redisHelper.hset(GlobalConstant.CACHE_USER_ROLENAMES, username, names); } return names; } /** * 根据用户id查询用户所有的权限名称 * @param username 用户名 * @return */ @SuppressWarnings("unchecked") public Set<String> findUserPermNames(String username){ Set<String> names= (Set<String>) redisHelper.hget(GlobalConstant.CACHE_USER_PERMNAMES,username); if(names==null) { names=userMapper.findUserPermNames(username); redisHelper.hset(GlobalConstant.CACHE_USER_PERMNAMES, username, names); } return names; } }
package com.tingcream.springshiro2.common.constant; public class GlobalConstant { public static final String SESSION_USER="sessionUser"; //缓存对象hash key是user field为username变量 value为user对象 public static final String CACHE_USER="user"; //缓存对象hash key为user_roleNames field为username变量 value为names List<String> public static final String CACHE_USER_ROLENAMES="user_roleNames"; //缓存对象hash key为user_permNames field为username变量 value为names List<String> public static final String CACHE_USER_PERMNAMES="user_permNames"; }
package com.tingcream.springshiro2.user.mapper; import java.util.Set; import com.tingcream.springshiro2.user.model.User; public interface UserMapper { /** * 根据用户名查询用户实体 * @param username 用户名 * @return */ public User findUserByUsername(String username); /** * 根据用户id查询用户所有的角色名称 * @param username 用户名 * @return */ public Set<String> findUserRoleNames(String username ); /** * 根据用户id查询用户所有的权限名称 * @param username 用户名 * @return */ public Set<String> findUserPermNames(String username); }
<?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.tingcream.springshiro2.user.mapper.UserMapper"> <!-- 根据用户名查询用户实体 --> <select id="findUserByUsername" parameterType="string" resultType="User"> select * from t_user t where t.username =#{_parameter} </select> <!-- 根据用户id查询用户所有的角色名称 --> <select id="findUserRoleNames" parameterType="string" resultType="string"> SELECT c.`roleName` FROM t_user a JOIN t_user_role b ON a.`userId`=b.`userId` JOIN t_role c ON b.`roleId`=c.`roleId` WHERE a.username=#{_parameter} </select> <!-- 根据用户id查询用户所有的权限名称 --> <select id="findUserPermNames" parameterType="string" resultType="string"> SELECT e.`permName` FROM t_user a JOIN t_user_role b ON a.`userId`=b.`userId` JOIN t_role c ON b.`roleId`=c.`roleId` JOIN t_role_permission d ON c.`roleId`=d.`roleId` JOIN t_permission e ON d.`permId`=e.`permId` WHERE a.username=#{_parameter} </select> </mapper>
package com.tingcream.springshiro2.user.model; import java.io.Serializable; /** * 用户实体 * @author jelly * */ public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer userId; private String username; private String password; private String createtime; 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 getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getCreatetime() { return createtime; } public void setCreatetime(String createtime) { this.createtime = createtime; } }
package com.tingcream.springshiro2.student.controller; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequiresRoles(value="student") @RequestMapping("/student") public class StudentController { @RequestMapping("/") public String index() { return "/student.jsp"; } }
package com.tingcream.springshiro2.teacher.controller; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequiresRoles("teacher") @RequestMapping("/teacher") public class TeacherController { @RequestMapping("/") public String index() { return "/teacher.jsp"; } }
db.sql
/* SQLyog Ultimate v12.5.0 (64 bit) MySQL - 5.7.16 : Database - springshiro ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`springshiro` /*!40100 DEFAULT CHARACTER SET utf8 */; /*Table structure for table `t_permission` */ DROP TABLE IF EXISTS `t_permission`; CREATE TABLE `t_permission` ( `permId` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id', `permName` varchar(50) DEFAULT NULL COMMENT '权限名称', `remark` varchar(50) DEFAULT NULL COMMENT '备注', `createtime` varchar(24) DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`permId`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; /*Data for the table `t_permission` */ insert into `t_permission`(`permId`,`permName`,`remark`,`createtime`) values (1,'student:add','学生添加','2019-03-25 13:41:18'), (2,'student:update','学生修改','2019-03-25 13:41:21'), (3,'student:delete','学生删除','2019-03-25 13:41:21'), (4,'student:find','学生查询','2019-03-25 13:41:21'), (5,'teacher:add','老师添加','2019-03-25 13:41:56'), (6,'teacher:update','老师修改','2019-03-25 13:41:56'), (7,'teacher:delete','老师删除','2019-03-25 13:41:56'), (8,'teacher:find','老师查询','2019-03-25 13:41:57'); /*Table structure for table `t_role` */ DROP TABLE IF EXISTS `t_role`; CREATE TABLE `t_role` ( `roleId` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id', `roleName` varchar(32) DEFAULT NULL COMMENT '角色名称', `remark` varchar(50) DEFAULT NULL COMMENT '备注', `createtime` varchar(24) DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`roleId`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*Data for the table `t_role` */ insert into `t_role`(`roleId`,`roleName`,`remark`,`createtime`) values (1,'student','学生','2019-03-25 13:36:31'), (2,'teacher','老师','2019-03-25 13:36:33'); /*Table structure for table `t_role_permission` */ DROP TABLE IF EXISTS `t_role_permission`; CREATE TABLE `t_role_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `roleId` int(11) DEFAULT NULL, `permId` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `roleId` (`roleId`), KEY `permId` (`permId`), CONSTRAINT `t_role_permission_ibfk_1` FOREIGN KEY (`roleId`) REFERENCES `t_role` (`roleId`), CONSTRAINT `t_role_permission_ibfk_2` FOREIGN KEY (`permId`) REFERENCES `t_permission` (`permId`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; /*Data for the table `t_role_permission` */ insert into `t_role_permission`(`id`,`roleId`,`permId`) values (1,1,1), (2,1,2), (3,1,3), (4,1,4), (5,2,5), (6,2,6), (7,2,7), (8,2,8); /*Table structure for table `t_user` */ DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `userId` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) DEFAULT NULL, `password` varchar(32) DEFAULT NULL, `createtime` varchar(24) DEFAULT NULL, PRIMARY KEY (`userId`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*Data for the table `t_user` */ insert into `t_user`(`userId`,`username`,`password`,`createtime`) values (1,'zhangsan','123456','2019-03-24 13:33:34'), (2,'lisi','123456','2019-03-24 13:33:34'); /*Table structure for table `t_user_role` */ DROP TABLE IF EXISTS `t_user_role`; CREATE TABLE `t_user_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) DEFAULT NULL, `roleId` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `userId` (`userId`), KEY `roleId` (`roleId`), CONSTRAINT `t_user_role_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `t_user` (`userId`), CONSTRAINT `t_user_role_ibfk_2` FOREIGN KEY (`roleId`) REFERENCES `t_role` (`roleId`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*Data for the table `t_user_role` */ insert into `t_user_role`(`id`,`userId`,`roleId`) values (1,1,1), (2,2,2); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
SpringContextAware.java (可从spring容器中手动获取bean)
package com.tingcream.springshiro2.common; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextAware implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextAware.applicationContext = applicationContext; } /** * 获取spring容器的 applicationContext 上下文对象 * @return */ public static ApplicationContext getApplicationContext(){ return applicationContext; } public static Object getBean(String name){ return applicationContext.getBean(name); } /** * 从spring 上下文中获取bean * @param <T> * @param name * @param requiredClass * @return */ public static <T> T getBean(String name, Class<T> requiredClass){ return applicationContext.getBean(name, requiredClass); } public static <T> T getBean(Class<T> requiredType){ return applicationContext.getBean(requiredType); } }
Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1