基于springboot-1.5.17构建,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>1.5.17.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>
<!-- <version>4.3.20.RELEASE</version> -->
</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>
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即可。
#服务器配置
server:
port: 8082
context-path: /
spring:
#devtools配置
devtools:
restart:
exclude: static/**
application:
name: springshiro
#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.springshiro: DEBUG
file: e:/log/springshiro/springshiro.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.springshiro"/>
</typeAliases>
<mappers>
<!--配置mapper接口和mapper.xml所在包(包含子包)-->
<package name="com.tingcream.springshiro"/>
</mappers>
</configuration>
package com.tingcream.springshiro;
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.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
@MapperScan(basePackages= {"com.tingcream.springshiro"})//可多个,含子包,支持通配符
public class SpringshiroApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringshiroApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringshiroApplication.class);
}
}
package com.tingcream.springshiro.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.springshiro.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.springshiro.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.springshiro.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.springshiro.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.springshiro.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.springshiro.user.model.User;
import com.tingcream.springshiro.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.springshiro.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.springshiro.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.springshiro.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.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
@RequestMapping(value="/home",method=RequestMethod.GET)
public String index(HttpServletRequest request,HttpServletResponse response) {
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() {
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.springshiro.user.service;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.tingcream.springshiro.common.constant.GlobalConstant;
import com.tingcream.springshiro.common.redis.RedisHelper;
import com.tingcream.springshiro.user.mapper.UserMapper;
import com.tingcream.springshiro.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.springshiro.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.springshiro.user.mapper;
import java.util.Set;
import com.tingcream.springshiro.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.springshiro.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.springshiro.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.springshiro.student.controller;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/student")
@RequiresRoles(value="student")
public class StudentController {
@RequestMapping("/")
public String index() {
return "/student.jsp";
}
}
package com.tingcream.springshiro.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.springshiro.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