日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot整合shiro和session的详细过程和自定义登录拦截器

發(fā)布時間:2024/9/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot整合shiro和session的详细过程和自定义登录拦截器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1.shiro依賴
  • 2.shiro配置
    • shiro過濾器配置:
    • 關聯(lián)自定義的其他管理器
    • 自定義會話工廠:
  • 3.登陸時記錄用戶信息
  • 4.shiro一些工具類的學習
  • 5.自定義登錄攔截器

shiro是一個安全框架,用于認證和授權,我覺得與springsecurity相比它上手更容易,同時如果是簡單的登錄攔截也可以用登錄攔截器實現,下面先進行springboot整合 shiro的過程

1.shiro依賴

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.7.1</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.7.1</version></dependency>

2.shiro配置

配置安全管理器:SecurityManager
Authenticator 的職責是驗證用戶帳號,是ShiroAPI 中身份驗證核心的入口點:如果驗證成功,將返回AuthenticationInfo驗證信息;此信息中包含了身份及憑證;如果驗證失敗將拋出相應的AuthenticationException異常
?SecurityManager接口繼承了Authenticator,另外還有一個ModularRealmAuthenticator實現,其委托給多個Realm 進行驗證,驗證規(guī)則通過AuthenticationStrategy接口指定

/*** 安全管理器*/@Beanpublic SecurityManager securityManager(UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 設置realm.securityManager.setRealm(userRealm);// 記住我securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);// 注入緩存管理器;securityManager.setCacheManager(getEhCacheManager());// session管理器securityManager.setSessionManager(sessionManager());return securityManager;}

哪些url是需要攔截的,哪些是不需要攔截的,登錄頁面、登錄成功頁面的url、自定義的Realm等這些信息需要設置到Shiro中

shiro過濾器配置:

/*** Shiro過濾器配置*/@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// Shiro的核心安全接口,這個屬性是必須的shiroFilterFactoryBean.setSecurityManager(securityManager);// 身份認證失敗,則跳轉到登錄頁面的配置shiroFilterFactoryBean.setLoginUrl(loginUrl);// 權限認證失敗,則跳轉到指定頁面shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);// Shiro連接約束配置,即過濾鏈的定義LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// 對靜態(tài)資源設置匿名訪問filterChainDefinitionMap.put("/favicon.ico**", "anon");//加入自己的路徑和訪問權限// 系統(tǒng)權限列表// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());Map<String, Filter> filters = new LinkedHashMap<String, Filter>();filters.put("onlineSession", onlineSessionFilter());filters.put("syncOnlineSession", syncOnlineSessionFilter());filters.put("captchaValidate", captchaValidateFilter());filters.put("kickout", kickoutSessionFilter());// 注銷成功,則跳轉到指定頁面filters.put("logout", logoutFilter());shiroFilterFactoryBean.setFilters(filters);// 所有請求需要認證filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}

安全管理器關聯(lián)自己的Realm

@Bean(name="security")public DefaultWebSecurityManager getDefaultManager(@Qualifier("realm")UserRealm userRealm){DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();//關聯(lián)自己的realmdefaultSecurityManager.setRealm(userRealm);return defaultSecurityManager;}@Bean(name = "realm")//創(chuàng)建realm對象public UserRealm userRealm(){return new UserRealm();}

關聯(lián)自定義的其他管理器

@Beanpublic SecurityManager securityManager(UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 設置realm.securityManager.setRealm(userRealm);// 記住我securityManager.setRememberMeManager(rememberMe ? rememberMeManager() : null);// 注入緩存管理器;securityManager.setCacheManager(getEhCacheManager());// session管理器securityManager.setSessionManager(sessionManager());return securityManager;}/*** 緩存管理器 使用Ehcache實現*/@Beanpublic EhCacheManager getEhCacheManager(){net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruoyi");EhCacheManager em = new EhCacheManager();if (StringUtils.isNull(cacheManager)){em.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));return em;}else{em.setCacheManager(cacheManager);return em;}}

緩存:Shiro內部相應的組件(DefaultSecurityManager)會自動檢測相應的對象(如Realm)是否實現了CacheManagerAware并自動注入相應的CacheManager。
Shiro提供了CachingRealm,其實現了CacheManagerAware接口,提供了緩存的一些基礎實現;
?AuthenticatingRealm及AuthorizingRealm也分別提供了對AuthenticationInfo和AuthorizationInfo信息的緩存。
Session 緩存
?如SecurityManager實現了SessionSecurityManager,其會判斷SessionManager是否實現了CacheManagerAware接口,如果實現了會把CacheManager設置給它。
?SessionManager也會判斷相應的SessionDAO(如繼承自CachingSessionDAO)是否實現了CacheManagerAware,如果實現了會把CacheManager設置給它
?設置了緩存的SessionManager,查詢時會先查緩存,如果找不到才查數據庫。

自定義會話工廠:

//自定義sessionFactory會話 @Component public class OnlineSessionFactory implements SessionFactory {@Overridepublic Session createSession(SessionContext initData){OnlineSession session = new OnlineSession();if (initData != null && initData instanceof WebSessionContext){WebSessionContext sessionContext = (WebSessionContext) initData;HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();if (request != null){UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));// 獲取客戶端操作系統(tǒng)String os = userAgent.getOperatingSystem().getName();// 獲取客戶端瀏覽器String browser = userAgent.getBrowser().getName();session.setHost(IpUtils.getIpAddr(request));session.setBrowser(browser);session.setOs(os);}}return session;} }

3.登陸時記錄用戶信息

在控制器層:

@ApiOperation(value="登錄") @PostMapping("/login")public ResponseResult<User> toLogin(@ApiParam(name="用戶對象",value="傳入json格式",required=true)LoginForm loginForm) {User user = userService.selectUserByLoginName(loginForm.getUserName(),loginForm.getPassword(), false);if (user != null) {UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword(), false);Subject subject = SecurityUtils.getSubject(); subject.login(token); return ResponseResult.success();}else return ResponseResult.error(); }

4.shiro一些工具類的學習

SecurityUtils.getSubject()是每個請求創(chuàng)建一個Subject, 并保存到ThreadContext的resources(ThreadLocal<Map<Object, Object>>)變量中,也就是一個http請求一個subject,并綁定到當前線程。
subject.login()登陸認證成功后,下一次請求如何知道是那個用戶的請求呢?
內部原理:1個請求1個Subject原理:由于ShiroFilterFactoryBean本質是個AbstractShiroFilter過濾器,所以每次請求都會執(zhí)行doFilterInternal里面的createSubject方法。
源碼:

public interface Subject {Object getPrincipal();PrincipalCollection getPrincipals();boolean isPermitted(String var1);boolean isPermitted(Permission var1);...省略其他方法}public interface SecurityManager extends Authenticator, Authorizer, SessionManager {Subject login(Subject var1, AuthenticationToken var2) throws AuthenticationException;void logout(Subject var1);Subject createSubject(SubjectContext var1); }public abstract class SecurityUtils {private static volatile SecurityManager securityManager;public SecurityUtils() {}public static Subject getSubject() {Subject subject = ThreadContext.getSubject();if (subject == null) {subject = (new Builder()).buildSubject();ThreadContext.bind(subject);}return subject;}public static void setSecurityManager(SecurityManager securityManager) {SecurityUtils.securityManager = securityManager;}public static SecurityManager getSecurityManager() throws UnavailableSecurityManagerException {SecurityManager securityManager = ThreadContext.getSecurityManager();if (securityManager == null) {securityManager = SecurityUtils.securityManager;}if (securityManager == null) {String msg = "No SecurityManager accessible to the calling code, either bound to the " + ThreadContext.class.getName() + " or as a vm static singleton. This is an invalid application configuration.";throw new UnavailableSecurityManagerException(msg);} else {return securityManager;}} }

shiro內置的session
session.setAttribute(“username”,username)就是將username保存到session中,session的key值為username,其信息(value)為username,或者引用值。這樣以后可以通過session.getAttribute(“username”)的方法來獲取這個對象。通常,當用戶已經登錄系統(tǒng)后,就可以在session中存儲一個用戶信息對象,伺候可以隨時從session中將這個對象取出來進行一些操作,比如身份驗證等等。

request.getSession()可以獲得HttpSession類型的對象,通常稱之為session對象,session對象的作用域為一次會話,通常瀏覽器不關閉,保存的值就不會消失,當然也會出現session超時。服務器里面可以設置session的超時時間,web.xml中有一個session time out的地方,tomcat默認為30分鐘。
session. setAttribute(“key”,value)是session設置值的方法,原理同Map集合。
getAttribute的返回值類型是Object,需要向下轉型,轉成你的userName類型的。比如,String session1= (String)session.getAttribute(“student”) ;

5.自定義登錄攔截器

這種辦法不需要引入依賴,只需要繼承HandlerInterceptor 即可 實現非常簡單:

@Slf4j public class UserLoginInterceptor implements HandlerInterceptor {/*** true 表示繼續(xù)流程,false表示中斷* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle...");User user = (User) request.getSession().getAttribute(MallConst.CURRENT_USER);if (user == null) {log.info("user=null");throw new UserLoginException();}return true;} }

然后定義一個配置類,啟動時springboot便能進行自動配置

@Configuration public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserLoginInterceptor()).addPathPatterns("/**")//自己添加需要攔截的路徑.excludePathPatterns("/error", "/user/login", "/user/register", "/categories", "/products/*");//哪些路徑不需要攔截} }

總結

以上是生活随笔為你收集整理的springboot整合shiro和session的详细过程和自定义登录拦截器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。