激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - spring整合shiro框架的實(shí)現(xiàn)步驟記錄

spring整合shiro框架的實(shí)現(xiàn)步驟記錄

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

Shiro是一個(gè)強(qiáng)大易用的Java安全框架,提供了認(rèn)證、授權(quán)、加密和會(huì)話管理等功能。下面這篇文章主要給大家介紹了關(guān)于spring整合shiro框架的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

shiro

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

 ?。?)Authentication(認(rèn)證)

 ?。?)Authorization(授權(quán))

  (3)Session Management(會(huì)話管理)

 ?。?)Cryptography (加密)

首先,認(rèn)證服務(wù),也就是說(shuō)通過(guò)她可以完成身份認(rèn)證,讓她去判斷用戶是否為真實(shí)的會(huì)員。

其次,授權(quán)服務(wù),說(shuō)白了就是“訪問(wèn)控制”服務(wù),也就是讓她來(lái)識(shí)別用戶擁有哪些權(quán)限。再說(shuō)的白一點(diǎn),就是通過(guò)判斷用戶是什么角色,來(lái)賦予他哪些操作權(quán)限。

然后,還有會(huì)話管理服務(wù), 這時(shí)一個(gè)獨(dú)立的Session管理框架,和我們熟知的Http Session 不太一樣。

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

今天,我就不全說(shuō)了,重點(diǎn)說(shuō)下她的 會(huì)話管理功能, 其實(shí)這個(gè)也是幾乎所有的web應(yīng)該都會(huì)涉及到的。

在說(shuō)shiro的會(huì)話管理服務(wù)前,先回顧下之前的會(huì)話管理我們是怎么做的。

1、最初我們是直接用的web服務(wù)器的 Http Session的機(jī)制, 也就是用戶第一次進(jìn)來(lái)的話,web容器會(huì)為這個(gè)請(qǐng)求創(chuàng)建一個(gè)session,然后把這個(gè)session存儲(chǔ)起來(lái),通過(guò)將對(duì)應(yīng)的sessionId,作為cookie傳給客戶端,

如果客戶端再次向這個(gè)服務(wù)器發(fā)送請(qǐng)求的話,會(huì)自動(dòng)將這個(gè)sessionId帶過(guò)來(lái), 然后web服務(wù)器會(huì)根據(jù)客戶端帶過(guò)來(lái)的 sessionId, 判斷其對(duì)于的session 是否還存在于內(nèi)存中(session是有過(guò)期時(shí)間的,可以在web.xml文件里面配置),如果找不到對(duì)應(yīng)的session了,說(shuō)明已經(jīng)過(guò)了session失效時(shí)間,這時(shí)web服務(wù)器會(huì)再次為它創(chuàng)建一個(gè)session,然后和之前一樣,將這個(gè)新的sessionId傳給客戶端。

因此,我們可以通過(guò)這種機(jī)制,在程序里管理用戶的登錄會(huì)話,比如我們?cè)谟脩舻谝淮蔚卿洺晒螅瑢⒂脩舻幕拘畔⒋鎯?chǔ)在session里(比如:session.setAttribute("user", "userInfo") ),下次用戶再次訪問(wèn)的時(shí)候,我們根據(jù)獲取當(dāng)前session里的user信息

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

2、第二種方式,就是我們將存儲(chǔ)信息的地方轉(zhuǎn)移到第三方介質(zhì)中,比如緩存里,memecache或者Redis都可以,這種方式主要是因?yàn)榉植际较到y(tǒng)的出現(xiàn)而采用的。

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

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

這樣,我們?cè)谟脩粝麓卧L問(wèn)的時(shí)候(定義一個(gè)攔截器),就可以從cookie里取出對(duì)應(yīng)的tokenKey,然后用這個(gè)tokenKey去到緩存里取相應(yīng)的值,如果獲取不到,說(shuō)明這個(gè)key已經(jīng)失效了,提示用戶重新登錄。

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

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

1)、新建一個(gè) 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>  //這個(gè)類(lèi)是需要自己實(shí)現(xiàn)的
 <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean>
</beans>

2)、在web.xml 里配置相應(yīng)的 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)寫(xiě)一個(gè)實(shí)現(xiàn)類(lèi),繼承 AbstractSessionDAO,實(shí)現(xiàn)相應(yīng)的方法。

?
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) {    //這就是第一次訪問(wèn)的時(shí)候,創(chuàng)建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) {  //這個(gè)方法其實(shí)就是通過(guò)sessionId讀取session,每讀一次,都要重新設(shè)置失效時(shí)間
 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,然后將用戶信息設(shè)置進(jìn)去

?
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", "用戶名或密碼錯(cuò)誤");
  return "user/userLogin";
 }
 
 SecurityUtils.setSecurityManager(sm);
 Subject currentUser = SecurityUtils.getSubject();    
 currentUser.getSession().setAttribute("LOGIN_USER", user); 
 return "redirect:/employee/list";
 }
}

獲取當(dāng)前用戶,在shiro里是主題,然后獲取對(duì)應(yīng)的session,并將用戶信息設(shè)置進(jìn)去,是不是感覺(jué)有點(diǎn)像Http session的操作的樣子,哈哈。

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

?
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());      //如果是登錄頁(yè)面的請(qǐng)求,則不攔截,否則會(huì)陷入死循環(huán)
 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 {
 
 }
}

到這里就基本結(jié)束了,如果你現(xiàn)在直接訪問(wèn)主頁(yè)信息的話,它會(huì)自動(dòng)跳到登錄頁(yè)面。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

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

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 一区二区三区欧美精品 | 国产日韩大片 | 日本看片一区二区三区高清 | 超碰97在线人人 | 国产成人精品区一区二区不卡 | 午夜人体 | 在线观看视频亚洲 | 亚洲第一成av人网站懂色 | 久久精品操 | 91精品久久久久久久久网影视 | a视频在线播放 | 蜜桃视频在线观看视频 | 精品国产专区 | 亚洲网站在线观看视频 | 国产羞羞视频 | 成人勉费视频 | 72pao成人国产永久免费视频 | 免费看成年人视频在线 | 欧美日韩免费看 | 97se亚洲综合在线韩国专区福利 | 久国久产久精永久网页 | 国产88久久久国产精品免费二区 | 人人做人人看 | 日本s级毛片免费观看 | av性色全交蜜桃成熟时 | 激情97| 国产做爰| 精品呦女 | 色玖玖综合 | 日韩精品a在线观看 | 成人在线观看一区 | 青青草成人免费视频在线 | 亚洲精中文字幕二区三区 | 伊人网站| 中文字幕在线免费看 | 性欧美xxxx极品摘花 | 国产91精品亚洲精品日韩已满 | 成人免费网站在线观看视频 | 午夜精品久久久久久久久久久久久蜜桃 | 国产精品欧美久久久久一区二区 | 红杏网站永久免费视频入口 |