spring boot shiro整合
来源:互联网 发布:603881数据港股票 编辑:程序博客网 时间:2024/05/21 19:34
spring boot 整合shiro需要的jar
<properties><shiro.version>1.4.0</shiro.version></properties><dependencies><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><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-guice</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-quartz</artifactId><version>${shiro.version}</version></dependency></dependencies>
shiro配置类:
package com.zyc.springboot.config;import java.util.ArrayList;import java.util.Collection;import java.util.LinkedHashMap;import java.util.Map;import javax.servlet.Filter;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.cache.ehcache.EhCacheManager;import org.apache.shiro.session.SessionListener;import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;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.CookieRememberMeManager;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.apache.shiro.web.servlet.SimpleCookie;import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.beans.factory.annotation.Qualifier;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.data.redis.core.RedisTemplate;import org.springframework.web.filter.DelegatingFilterProxy;import com.zyc.springboot.shiro.MyFormAuthenticationFilter;import com.zyc.springboot.shiro.MyRealm;@Configurationpublic class ShiroConfig {@Bean(name = "shiroEhcacheManager")public EhCacheManager getEhCacheManager() {EhCacheManager em = new EhCacheManager();em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");return em;}@Bean(name = "lifecycleBeanPostProcessor")public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();return lifecycleBeanPostProcessor;}@Bean(name = "sessionValidationScheduler")public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler() {ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();scheduler.setInterval(900000);//scheduler.setSessionManager(defaultWebSessionManager());return scheduler;}@Beanpublic HashedCredentialsMatcher hashedCredentialsMatcher() {HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于md5(md5(""));return hashedCredentialsMatcher;}@Bean(name = "defaultWebSecurityManager")public DefaultWebSecurityManager defaultWebSecurityManager(MyRealm myRealm,DefaultWebSessionManager defaultWebSessionManager) {DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();defaultWebSecurityManager.setRealm(myRealm);defaultWebSecurityManager.setCacheManager(getEhCacheManager());defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);defaultWebSecurityManager.setRememberMeManager(rememberMeManager());return defaultWebSecurityManager;}@Bean(name = "rememberMeCookie")public SimpleCookie rememberMeCookie() {// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMeSimpleCookie simpleCookie = new SimpleCookie("rememberMe");// <!-- 记住我cookie生效时间30天 ,单位秒;-->simpleCookie.setMaxAge(259200);return simpleCookie;}/** * cookie管理对象; * * @return */@Bean(name = "rememberMeManager")public CookieRememberMeManager rememberMeManager() {CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();cookieRememberMeManager.setCookie(rememberMeCookie());return cookieRememberMeManager;}@Bean@DependsOn(value = "lifecycleBeanPostProcessor")public MyRealm myRealm() {MyRealm myRealm = new MyRealm();myRealm.setCacheManager(getEhCacheManager());myRealm.setCredentialsMatcher(hashedCredentialsMatcher());return myRealm;}@Bean@DependsOn("lifecycleBeanPostProcessor")public DefaultAdvisorAutoProxyCreator getAutoProxyCreator(){DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();creator.setProxyTargetClass(true);return creator;}@Beanpublic AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();aasa.setSecurityManager(defaultWebSecurityManager);return aasa;}@Bean(name = "sessionManager")public DefaultWebSessionManager defaultWebSessionManager(SessionDao sessionDao) {DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setGlobalSessionTimeout(18000000);////url中是否显示session IdsessionManager.setSessionIdUrlRewritingEnabled(false);//// 删除失效的sessionsessionManager.setDeleteInvalidSessions(true);sessionManager.setSessionValidationSchedulerEnabled(true);sessionManager.setSessionValidationInterval(18000000);sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler());//设置SessionIdCookie 导致认证不成功,不从新设置新的cookie,从sessionManager获取sessionIdCookie//sessionManager.setSessionIdCookie(simpleIdCookie());sessionManager.getSessionIdCookie().setName("session-z-id");sessionManager.getSessionIdCookie().setPath("/");sessionManager.getSessionIdCookie().setMaxAge(60*60*24*7);return sessionManager;}@Bean(name = "filterRegistrationBean1")public FilterRegistrationBean filterRegistrationBean() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");filterRegistrationBean.setEnabled(true);filterRegistrationBean.addUrlPatterns("/");return filterRegistrationBean;}@Bean(name = "shiroFilter")public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {// SecurityUtils.setSecurityManager(defaultWebSecurityManager);ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setLoginUrl("/login");shiroFilterFactoryBean.setSuccessUrl("/getMyJsp");shiroFilterFactoryBean.setUnauthorizedUrl("/login");shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);Map<String, Filter> filterMap1 = shiroFilterFactoryBean.getFilters();//自定义的filter 不能交给spring 容器管理,只能使用new 实例化filterfilterMap1.put("authc", new MyFormAuthenticationFilter());shiroFilterFactoryBean.setFilters(filterMap1);Map<String, String> filterMap = new LinkedHashMap<String, String>();filterMap.put("/static/**", "anon");filterMap.put("/logout", "logout"); filterMap.put("/login", "authc");filterMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}}MyRealm类如下:
package com.zyc.springboot.shiro;import java.lang.reflect.InvocationTargetException;import org.apache.commons.beanutils.BeanUtils;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.realm.Realm;import org.apache.shiro.subject.PrincipalCollection;import com.zyc.springboot.entity.User;public class MyRealm extends AuthorizingRealm {/** * 权限认证 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stub//获取登录用户的信息,在认证时存储的是ShiroUser 所以得到的就是ShiroUser//在其他地方也可通过SecurityUtils.getSubject().getPrincipals()获取用户信息ShiroUser sysUser = (ShiroUser) principals.getPrimaryPrincipal();//权限字符串List<String> permissions=new ArrayList<>();//从数据库中获取对应权限字符串并存储permissions//角色字符串List<String> roles=new ArrayList<>();//从数据库中获取对应角色字符串并存储rolesSimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();simpleAuthorizationInfo.addStringPermissions(permissions);simpleAuthorizationInfo.addRoles(roles);//角色类型return simpleAuthorizationInfo;}/** * 登录验证 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("认证=====");String userName=((MyAuthenticationToken) arg0).getUsername();char[] password=((MyAuthenticationToken) arg0).getPassword();User user=new User();//根据用户名密码获取user,这里不在连接数据库user.setPassword("e10adc3949ba59abbe56e057f20f883e");//123456 md5加密后的值user.setUserName("zyc");//user信息 本该从数据库中获取,这里为了简单,直接模拟if(user==null){throw new AuthenticationException("用户名密码错误");}ShiroUser shiroUser=new ShiroUser();//自定义的用户信息类,在shiro中存储使用try {BeanUtils.copyProperties(shiroUser, user);//user信息赋给shiroUser} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(shiroUser, user.getPassword(), this.getName());return simpleAuthenticationInfo;}}自定义filter MyFormAuthenticationFilter如下
package com.zyc.springboot.shiro;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import org.apache.shiro.web.util.WebUtils;import org.springframework.core.annotation.Order;public class MyFormAuthenticationFilter extends FormAuthenticationFilter {// 登录失败,异常抛出@Overrideprotected boolean onLoginFailure(AuthenticationToken token,AuthenticationException e, ServletRequest request,ServletResponse response) {String className = e.getClass().getName();if (e != null&& !UnknownAccountException.class.getName().equals(className)&& !IncorrectCredentialsException.class.getName().equals(className)&& !LockedAccountException.class.getName().equals(className)) { // 用户被锁定e.printStackTrace(); // 非验证异常抛出}return super.onLoginFailure(token, e, request, response);}// 重写认证通过后的页面跳转,shiro会默认跳转到上一次请求的页面,不适用于iframe的框架@Overrideprotected void issueSuccessRedirect(ServletRequest request,ServletResponse response) throws Exception {// 认证通过后的跳转地址System.out.println("认证通过后的跳转地址"+getSuccessUrl());WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true);}@Overrideprotected AuthenticationToken createToken(ServletRequest request,ServletResponse response) {System.out.println("create Token");String username = getUsername(request);String password = getPassword(request);boolean remberMe = isRememberMe(request);String host = "";String captcha = "";String ipAddr = "";return new MyAuthenticationToken(username, password, remberMe, host,captcha, ipAddr);}}自定义token类如下:
package com.zyc.springboot.shiro;import org.apache.shiro.authc.UsernamePasswordToken;/** * 用来存储验证码等其他信息 * @author Administrator * */public class MyAuthenticationToken extends UsernamePasswordToken {/** * */private static final long serialVersionUID = -2681757716434500100L;private String captcha;private String ipAddr;public MyAuthenticationToken(String username,String password,boolean rememberMe,String host,String captcha,String ipAddr) { super(username, password, rememberMe, host); this.captcha = captcha; this.ipAddr=ipAddr;}public String getCaptcha() {return captcha;}public void setCaptcha(String captcha) {this.captcha = captcha;}public String getIpAddr() {return ipAddr;}public void setIpAddr(String ipAddr) {this.ipAddr = ipAddr;}}shiro登录认证调用有2种认证方式,个人理解为主动触发和被动触发,
主动触发是通过调用subject.login(token)方法如下:这种方式shiro 的/login=anon
@RequestMapping("tologin")public String login(Model model, HttpServletRequest request,HttpServletResponse response) throws Exception {System.out.println("login =======start==");Subject subject = SecurityUtils.getSubject();subject.login(token);System.out.println("login ======end===");return "login";}
被动触发:是在shiro 的loginurl属性和登录表单的action跳转url 一致,get请求直接返回界面,post请求会调用认证 这种方式shiro 的/login=authc@RequestMapping("login")public String login(Model model, HttpServletRequest request,HttpServletResponse response) throws Exception {System.out.println("login =======start==");Subject subject = SecurityUtils.getSubject();if (subject.isAuthenticated()) { // 已经登录,跳转到自己的首页WebUtils.issueRedirect(request, response, "/getMyJsp");return "login";}System.out.println("login ======end===");return "login";}
问题小结:
shiro 登录后,样式不显示
可能原因,shiro的filter 把样式给拦截了,注意shiro自定义的filter 不能交给spring 管理,并且要注意拦截器的顺序,shiroFilter 在其他拦截器之前
shiro 报there is no session with id []
产生此原因可能是在代码中的某个地方调用了session.invalidate(),或者shiro 的logout方法,之后又使用了request,session的方法
shiro 点击登录,或者认证成功后继续点击,总是返回到登录页面
正常情况下如果认证失败会返回登录界面,如果认证通过了返回登录界面可以查看设置sessionManager 的setSessionIdCookie()是如何设置cookie的,尽量不要创建新的cookie 而是使用sessionManager.getSessionIdCookie()获取默认的cookie进行设置
阅读全文
1 0
- spring boot整合shiro
- spring boot shiro整合
- spring boot 整合shiro(一)
- spring boot shiro redis整合
- spring boot整合Shiro实现单点登录
- Spring boot 整合shiro 实现登陆验证
- Spring boot项目整合thymeleaf和shiro
- 【shiro】--- spring整合shiro
- Spring Boot Shiro权限管理--自定义 FormAuthenticationFilter验证码整合
- Spring Boot整合jpa,Shiro进行权限管理
- spring boot整合redis,实现shiro的CacheManager
- spring boot整合redis实现shiro的分布式session共享
- spring boot 使用thymeleaf 和shiro标签整合
- spring-boot集成shiro
- spring boot集成shiro
- spring boot +mybatis+shiro
- spring boot shiro
- [spring-boot] 集成shiro
- while 和 for 循环
- ArcGIS中Geodatabase简介
- php中的类与对象(继承)
- Python学习 第一天任务 (一)【基于Python编程从入门到实践】
- CoolHC Volume 1 By CoolFire
- spring boot shiro整合
- 电脑切换应用和软件分屏
- okhttp3封装 get post 请求 下载上传文件 Post请求发送JSON数据 判断下载目录是否存在......并返回绝对路径 从下载连接中解析出文件名
- [POJ](1088)滑雪 ---- 动态规划
- C# 读取 Geodatabase
- 程序关于调出键盘崩溃问题(系统为8.0的机器)
- WEB缓存_缓存层次
- 日记(2)
- 二分查找---月度开销