欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

shiro

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

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

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

 ?。?)Session Management(會話管理)

 ?。?)Cryptography (加密)

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

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

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

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

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

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

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

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

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

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

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

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

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

我們還要將生成的這個(gè)tokenKey通過cookie傳到客戶端: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);

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

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

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

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

<?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è)類是需要自己實(shí)現(xiàn)的
 <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean>
</beans>

2)、在web.xml 里配置相應(yīng)的 filter:

<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)寫一個(gè)實(shí)現(xiàn)類,繼承 AbstractSessionDAO,實(shí)現(xiàn)相應(yīng)的方法。

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) {    //這就是第一次訪問的時(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í)就是通過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)去

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里是主題,然后獲取對應(yīng)的session,并將用戶信息設(shè)置進(jìn)去,是不是感覺有點(diǎn)像Http session的操作的樣子,哈哈。

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

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());      //如果是登錄頁面的請求,則不攔截,否則會陷入死循環(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)在直接訪問主頁信息的話,它會自動跳到登錄頁面。

總結(jié)

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

相關(guān)文章

  • Java超詳細(xì)講解WebMvcConfigurer攔截器

    Java超詳細(xì)講解WebMvcConfigurer攔截器

    這篇文章將用實(shí)例來和大家介紹一下WebMvcConfigurer攔截器。文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下
    2022-06-06
  • java反射機(jī)制Reflection詳解

    java反射機(jī)制Reflection詳解

    在本篇文章里小編給大家分享了關(guān)于java反射機(jī)制Reflection的相關(guān)知識點(diǎn),需要的朋友們學(xué)習(xí)下。
    2019-04-04
  • SpringBoot實(shí)戰(zhàn)之實(shí)現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解

    SpringBoot實(shí)戰(zhàn)之實(shí)現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解

    這篇文章主要介紹了SpringBoot實(shí)戰(zhàn)之實(shí)現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • java后臺如何利用Pattern提取所需字符詳解

    java后臺如何利用Pattern提取所需字符詳解

    這篇文章主要給大家介紹了關(guān)于java后臺如何利用Pattern提取所需字符的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Intellij IDEA命令行執(zhí)行java無法加載主類解決方案

    Intellij IDEA命令行執(zhí)行java無法加載主類解決方案

    這篇文章主要介紹了Intellij IDEA命令行執(zhí)行java無法加載主類解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • tomcat的keepAlive參數(shù)深入探究

    tomcat的keepAlive參數(shù)深入探究

    這篇文章主要為大家介紹了tomcat的keepAlive參數(shù)深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Java中使用JavaScript腳本的方法步驟

    Java中使用JavaScript腳本的方法步驟

    這篇文章主要介紹了Java中使用JavaScript腳本的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 詳解Spring Boot 自定義PropertySourceLoader

    詳解Spring Boot 自定義PropertySourceLoader

    這篇文章主要介紹了詳解Spring Boot 自定義PropertySourceLoader,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):單鏈表與雙向鏈表

    java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):單鏈表與雙向鏈表

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)單鏈表、雙向鏈表的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 詳解Java設(shè)計(jì)模式編程中的中介者模式

    詳解Java設(shè)計(jì)模式編程中的中介者模式

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中的中介者模式,文中舉了典型的同事類與中介者類的例子來解釋說明,需要的朋友可以參考下
    2016-02-02

最新評論