国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - spring整合shiro框架的實現步驟記錄

spring整合shiro框架的實現步驟記錄

2021-04-28 11:58海小鑫 Java教程

Shiro是一個強大易用的Java安全框架,提供了認證、授權、加密和會話管理等功能。下面這篇文章主要給大家介紹了關于spring整合shiro框架的實現步驟,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

shiro

Shiro是Apache下的一個開源項目,我們稱之為Apache Shiro。它是一個很易用與Java項目的的安全框架,提供了認證、授權、加密、會話管理,與spring Security 一樣都是做一個權限的安全框架,但是與Spring Security 相比,在于 Shiro 使用了比較簡單易懂易于使用的授權方式。shiro屬于輕量級框架,相對于security簡單的多,也沒有security那么復雜。更多詳細的介紹可以從它的官網上(http://shiro.apache.org/)基本可以了解到,她主要提供以下功能:

  (1)Authentication(認證)

  (2)Authorization(授權)

  (3)Session Management(會話管理)

  (4)Cryptography (加密)

首先,認證服務,也就是說通過她可以完成身份認證,讓她去判斷用戶是否為真實的會員。

其次,授權服務,說白了就是“訪問控制”服務,也就是讓她來識別用戶擁有哪些權限。再說的白一點,就是通過判斷用戶是什么角色,來賦予他哪些操作權限。

然后,還有會話管理服務, 這時一個獨立的Session管理框架,和我們熟知的Http Session 不太一樣。

最后,她還提供了Cryptography(加密)服務,封裝了很多密碼學的算法。

今天,我就不全說了,重點說下她的 會話管理功能, 其實這個也是幾乎所有的web應該都會涉及到的。

在說shiro的會話管理服務前,先回顧下之前的會話管理我們是怎么做的。

1、最初我們是直接用的web服務器的 Http Session的機制, 也就是用戶第一次進來的話,web容器會為這個請求創建一個session,然后把這個session存儲起來,通過將對應的sessionId,作為cookie傳給客戶端,

如果客戶端再次向這個服務器發送請求的話,會自動將這個sessionId帶過來, 然后web服務器會根據客戶端帶過來的 sessionId, 判斷其對于的session 是否還存在于內存中(session是有過期時間的,可以在web.xml文件里面配置),如果找不到對應的session了,說明已經過了session失效時間,這時web服務器會再次為它創建一個session,然后和之前一樣,將這個新的sessionId傳給客戶端。

因此,我們可以通過這種機制,在程序里管理用戶的登錄會話,比如我們在用戶第一次登錄成功后,將用戶的基本信息存儲在session里(比如:session.setAttribute("user", "userInfo") ),下次用戶再次訪問的時候,我們根據獲取當前session里的user信息

session.getAttribute("user") ),來判斷用戶是否過期,如果獲取不到,那么提示用戶重新登錄。

2、第二種方式,就是我們將存儲信息的地方轉移到第三方介質中,比如緩存里,memecache或者Redis都可以,這種方式主要是因為分布式系統的出現而采用的。

這種情況下,就需要我們自己生成sessionId了,一般我們會用一個定義好的前綴(user:login:token)再加上userid,或者時間戳都可以。 然后我們會將這個sessionId作為緩存的key, 用戶的信息作為value,存入緩存中,并設置失效時間:

?
1
2
jedisClient.set(tokenKey, JsonUtil.toJSONString(userInfo));
jedisClient.expire(tokenKey, TOKEN_LOSE_SECONDS);

這樣,我們在用戶下次訪問的時候(定義一個攔截器),就可以從cookie里取出對應的tokenKey,然后用這個tokenKey去到緩存里取相應的值,如果獲取不到,說明這個key已經失效了,提示用戶重新登錄。

注: tokenKey 很重要,她是連接緩存端和客戶端的樞紐。

3、最后一種就是我們shiro方式了,思路也類似,代碼挺簡單的,那我就直接上代碼吧:

1)、新建一個 applicationContext-shiro.xml文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
 
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
 <property name="securityManager" ref="securityManager"></property>
 <property name="loginUrl" value="/loginPage"></property>
 <property name="unauthorizedUrl" value="/pages/unauthorized.jsp"/>
 <property name="filterChainDefinitions">
 <value>
 /jcaptcha* = anon
 /logout = anon
 </value>
 </property>
 </bean>
 
 <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
 <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"></property>
 <property name="arguments" ref="securityManager"></property>
 </bean>
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
 <property name="cacheManager" ref="cacheManager"></property>
 <property name="sessionManager" ref="sessionManager"></property>
 </bean>
 <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
 <property name="sessionDAO" ref="sessionDAO"></property>
 </bean>
 <bean id="sessionDAO" class="com.smart.core.shiro.MySessionDAO"></bean>  //這個類是需要自己實現的
 <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean>
</beans>

2)、在web.xml 里配置相應的 filter:

?
1
2
3
4
5
6
7
8
9
10
11
12
<filter>
 <filter-name>shiroFilter</filter-name>
 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 <init-param>
  <param-name>targetFilterLifecycle</param-name>
  <param-value>true</param-value>
 </init-param>
 </filter>
 <filter-mapping>
 <filter-name>shiroFilter</filter-name>
 <url-pattern>/*</url-pattern>
 </filter-mapping>

3)寫一個實現類,繼承 AbstractSessionDAO,實現相應的方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.jdd.core.shiro;
 
import com.smart.core.redis.RedisManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.SerializationUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
 
public class MySessionDAO extends AbstractSessionDAO {
 
 @Autowired
 private RedisManager redisManager;
 
 @Override
 public void update(Session session) throws UnknownSessionException {
 redisManager.set(SerializationUtils.serialize(session.getId().toString()), SerializationUtils.serialize(session));
 redisManager.expire(SerializationUtils.serialize(session.getId().toString()), 60);
 }
 
 @Override
 public void delete(Session session) {
 redisManager.del(SerializationUtils.serialize(session.getId().toString()));
 }
 
 @Override
 public Collection<Session> getActiveSessions() {
 return new ArrayList<Session>();
 }
 
 @Override
 protected Serializable doCreate(Session session) {    //這就是第一次訪問的時候,創建sessionId
 Serializable sid = this.generateSessionId(session);
 assignSessionId(session, sid);
 redisManager.set(SerializationUtils.serialize(session.getId().toString()), SerializationUtils.serialize(session));
 redisManager.expire(SerializationUtils.serialize(session.getId().toString()), 60);
 return sid;
 }
 
 @Override
 protected Session doReadSession(Serializable serializable) {  //這個方法其實就是通過sessionId讀取session,每讀一次,都要重新設置失效時間
 byte[] aa = redisManager.get(SerializationUtils.serialize(serializable.toString()));
 Session session = (Session) SerializationUtils.deserialize(aa);
 redisManager.set(SerializationUtils.serialize(serializable.toString()), SerializationUtils.serialize(session));
 redisManager.expire(SerializationUtils.serialize(serializable.toString()), 60);
 return session;
 }
}

4)下一步,我就是要在登錄成功之后的邏輯里,獲取到shiro 的session,然后將用戶信息設置進去

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.smart.controller;
import com.smart.pojo.User;
import com.smart.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@Controller
@RequestMapping("/user")
public class UserController {
 
 @Autowired
 private UserService userService;
 @Autowired
 private SecurityManager sm;  //注入SecurityManager
 
 private Logger logger = LoggerFactory.getLogger(UserController.class);
 
 @RequestMapping(value = "/loginPage")
 public String loginPage(){
 return "user/userLogin";
 }
 
 @RequestMapping(value = "/userLogin", method = RequestMethod.POST)
 public String userLogin(@RequestParam(value="name") String name, @RequestParam(value="pwd") String pwd, Model model){
 
 logger.info("enter userLogin...");
 User user = userService.getUserByNameAndPassword(name, pwd);
 if(user == null){
  logger.info("user is not exist...");
  model.addAttribute("login_error", "用戶名或密碼錯誤");
  return "user/userLogin";
 }
 
 SecurityUtils.setSecurityManager(sm);
 Subject currentUser = SecurityUtils.getSubject();    
 currentUser.getSession().setAttribute("LOGIN_USER", user); 
 return "redirect:/employee/list";
 }
}

獲取當前用戶,在shiro里是主題,然后獲取對應的session,并將用戶信息設置進去,是不是感覺有點像Http session的操作的樣子,哈哈。

5)、最后,定義一個springmvc 的攔截器,在攔截器里獲取相應的session里的而用戶信息,如果獲取不到,則跳轉到登錄界面。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.smart.core.shiro;
 
import com.smart.pojo.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class LoginInterceptor implements HandlerInterceptor {
 
 private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
 
 @Autowired
 private SecurityManager sm;
 
 @Override
 public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
 logger.info("enter LoginInterceptor...");
 HttpServletRequest request = httpServletRequest;
 HttpServletResponse response = httpServletResponse;
 logger.info("request uri===>"+request.getRequestURI());      //如果是登錄頁面的請求,則不攔截,否則會陷入死循環
 if(request.getRequestURI().contains("loginPage") || request.getRequestURI().contains("userLogin")){
  return true;
 }else{
  SecurityUtils.setSecurityManager(sm);
  Subject currentUser = SecurityUtils.getSubject();
  Object obj = currentUser.getSession().getAttribute("LOGIN_USER");
  if(obj==null){
  response.sendRedirect("http://localhost:8080/user/loginPage");
  return false;
  }else{
  User user = (User)obj;
  if(user==null || user.getName()==null){
   response.sendRedirect("http://localhost:8080/user/loginPage");
   return false;
  }else{
   return true;
  }
  }
 
 }
 
 }
 
 @Override
 public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
 
 }
 
 @Override
 public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
 
 }
}

到這里就基本結束了,如果你現在直接訪問主頁信息的話,它會自動跳到登錄頁面。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/xiexin2015/p/9031785.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩精品在线视频 | 国产综合在线视频 | 爱爱视频网址 | 一区视频在线播放 | 天天艹| 亚洲激情综合 | 久久久久久国产精品mv | 日日天天 | 欧美日韩国产一区二区三区 | 亚洲激情在线播放 | 美日韩精品 | 九九久久影视 | 亚洲精品久久久 | 欧美一级特黄在线观看 | 久久男人免费视频 | 全部古装三级在线播放 | av片在线播放 | 久久大| 91成人短视频在线观看 | 精品国产91亚洲一区二区三区www | 九九99九九| 日韩欧美中文字幕一区二区三区 | 91色在线视频 | 久久久久久夜 | 免费观看全黄做爰大片国产 | 免费精品 | 国产精品国产成人国产三级 | 日韩一级免费观看 | 欧美一级看片a免费观看 | 人人九九精 | 亚洲美女精品视频 | 水密桃av | jvid精品资源在线观看 | 在线国产视频 | 免费在线看黄 | 精品视频一区二区三区 | 成人免费激情视频 | 日韩精品亚洲一区 | 黄色av电影| 丁香五月网久久综合 | 国产欧美一区二区三区在线看 |