<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.6.0</version>
</dependency>
shiro基本配置:
package com.demo1.config;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.session.mgt.DefaultSessionManager;
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.mgt.DefaultWebSubjectFactory;
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 org.apache.shiro.mgt.SecurityManager;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
/**
* 自定义Realm
*/
@Bean
public MyRealm myRealm(){
MyRealm myShiroRealm = new MyRealm();
// myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
@Bean
public FilterRegistrationBean delegatingFilterProxy() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
proxy.setTargetFilterLifecycle(true);
proxy.setTargetBeanName("shiroFilter");
filterRegistrationBean.setFilter(proxy);
return filterRegistrationBean;
}
@Bean("shiroFilter")
@DependsOn("securityManager")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
// 拦截器
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 验证码允许匿名访问
// filterChainDefinitionMap.put("/**/test1", "anon");
filterChainDefinitionMap.put("/**", "jwt");
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("jwt", new MyFilter());
shiroFilter.setFilters(filters);
//未授权界面;
shiroFilter.setUnauthorizedUrl("/unauthorized");
return shiroFilter;
}
/**
* Subject工厂管理器
*/
@Bean
public DefaultWebSubjectFactory subjectFactory(){
return new StatelessDefaultSubjectFactory();
}
/**
* 安全管理器
*/
@Bean("securityManager")
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 注入自定义Realm
securityManager.setRealm(myRealm());
// 替换默认的DefaultSubjectFactory,用于关闭session功能
securityManager.setSubjectFactory(subjectFactory());
securityManager.setSessionManager(sessionManager());
// 关闭session存储,禁用Session作为存储策略的实现,但它没有完全地禁用Session所以需要配合SubjectFactory中的context.setSessionCreationEnabled(false)
((DefaultSessionStorageEvaluator) ((DefaultSubjectDAO)securityManager.getSubjectDAO()).getSessionStorageEvaluator()).setSessionStorageEnabled(false);
// 用户授权/认证信息Cache, 后期可采用EhCache缓存
// securityManager.setCacheManager(cacheManager());
SecurityUtils.setSecurityManager(securityManager);
return securityManager;
}
/**
* 会话管理器
*/
public DefaultSessionManager sessionManager(){
DefaultSessionManager sessionManager =new DefaultSessionManager();
// 关闭session定时检查,通过setSessionValidationSchedulerEnabled禁用掉会话调度器
sessionManager.setSessionValidationSchedulerEnabled(false);
return sessionManager;
}
/**
* 用户授权信息缓存
*/
@Bean
public CacheManager cacheManager() {
// EhCacheManager cacheManager = new EhCacheManager();
// cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
return new MemoryConstrainedCacheManager();
}
// /**
// * 凭证匹配器(由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了)
// */
// @Bean
// public HashedCredentialsMatcher hashedCredentialsMatcher(){
// HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// // 散列算法:这里使用MD5算法;
// hashedCredentialsMatcher.setHashAlgorithmName("md5");
// // 散列的次数,比如散列两次,相当于 md5(md5(""));
// hashedCredentialsMatcher.setHashIterations(2);
// return hashedCredentialsMatcher;
// }
/**
* 下面的代码是添加注解支持
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// 强制使用cglib,防止重复代理和可能引起代理出错的问题
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
* Shiro生命周期处理器
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 开启shiro aop注解支持.使用代理方式;所以需要开启代码支持;
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
无Session工厂:
package com.demo1.config;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
/**
* 通过调用context.setSessionCreationEnabled(false)表示不创建会话,
* 如果之后调用Subject.getSession()将抛出DisabledSessionException异常。
* @author hqp
* @date 2019/6/17 10:24
*/
public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {
@Override
public Subject createSubject(SubjectContext context) {
// 不创建session
context.setSessionCreationEnabled(false);
return super.createSubject(context);
}
}
realm:
package com.demo1.config;
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;
public class MyRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("授权");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addStringPermission("teacher1");
authorizationInfo.addStringPermission("teacher2");
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("认证");
return new SimpleAuthenticationInfo(
//用户
"account!!!!",
//密码
"123",
//salt=username+salt
null,
//realm name
getName()
);
}
}
过滤器:
package com.demo1.config;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class MyFilter extends BasicHttpAuthenticationFilter {
@Autowired
HttpServletRequest request;
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
System.out.println("isAccessAllowed");
return false;
}
/**
* 判断用户是否想要登入。
* 检测header里面是否包含Authorization字段即可
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
System.out.println("isLoginAttempt");
return true;
}
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) {
System.out.println("executeLogin");
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("yaoct", "123");
Subject subject= SecurityUtils.getSubject();
subject.login(usernamePasswordToken);
return true;
}
}
controller:
package com.demo1.controller;
import com.demo1.entity.Student;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;
@RestController
public class TestController {
@GetMapping("/test1")
@RequiresPermissions({"teacher1","teacher2"})
String test1(String p1,String p2){
System.out.println(p1+",,"+p2);
Subject subject = SecurityUtils.getSubject();
return (String)subject.getPrincipal();
}
@PostMapping("/test2")
String test1(@RequestBody Student student,String p1,String p2){
System.out.println(student);
return "成功!";
}
}