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

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

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

服務器之家 - 編程語言 - Java教程 - spring boot整合Shiro實現單點登錄的示例代碼

spring boot整合Shiro實現單點登錄的示例代碼

2021-03-27 13:43牛奮lch Java教程

本篇文章主要介紹了spring boot整合Shiro實現單點登錄的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

Shiro是什么

Shiro是一個Java平臺的開源權限框架,用于認證和訪問授權。具體來說,滿足對如下元素的支持:

  1. 用戶,角色,權限(僅僅是操作權限,數據權限必須與業務需求緊密結合),資源(url)。
  2. 用戶分配角色,角色定義權限。
  3. 訪問授權時支持角色或者權限,并且支持多級的權限定義。

Q:對組的支持?
A:shiro默認不支持對組設置權限。

Q:是否可以滿足對組進行角色分配的需求?
A:擴展Realm,可以支持對組進行分配角色,其實就是給該組下的所有用戶分配權限。

Q:對數據權限的支持? 在業務系統中定義?
A:shiro僅僅實現對操作權限的控制,用于在前端控制元素隱藏或者顯示,以及對資源訪問權限進行檢查。數據權限與具體的業務需求緊密關聯,shiro本身無法實現對數據權限的控制。

Q:動態權限分配?
A:擴展org.apache.shiro.realm.Realm,支持動態權限分配。

Q:與Spring集成?
A:可以支持與Spring集成,shiro還支持jsp標簽。

前面的博客中,我們說道了Shiro的兩個最大的特點,認證和授權,而單點登錄也是屬于認證的一部分,默認情況下,Shiro已經為我們實現了和Cas的集成,我們加入集成的一些配置就ok了。

1、加入shiro-cas包

?
1
2
3
4
5
6
<!-- shiro整合cas單點 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-cas</artifactId>
      <version>1.2.4</version>
    </dependency>

2、加入單點登錄的配置

這里,我將所有的配置都貼出來,方便參考,配置里面已經加了詳盡的說明。

?
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
package com.chhliu.springboot.shiro.config; 
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.cas.CasFilter;
import org.apache.shiro.cas.CasSubjectFactory;
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.DefaultWebSecurityManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.DelegatingFilterProxy;
 
/**
 * Shiro 配置
 *
 * Apache Shiro 核心通過 Filter 來實現,就好像SpringMvc 通過DispachServlet 來主控制一樣。 既然是使用
 * Filter 一般也就能猜到,是通過URL規則來進行過濾和權限校驗,所以我們需要定義一系列關于URL的規則和訪問權限。
 *
 * @author chhliu
 */
@Configuration
public class ShiroConfiguration {
   
  // cas server地址
  public static final String casServerUrlPrefix = "http://127.0.0.1";
  // Cas登錄頁面地址
  public static final String casLoginUrl = casServerUrlPrefix + "/login";
  // Cas登出頁面地址
  public static final String casLogoutUrl = casServerUrlPrefix + "/logout";
  // 當前工程對外提供的服務地址
  public static final String shiroServerUrlPrefix = "http://127.0.1.28:8080";
  // casFilter UrlPattern
  public static final String casFilterUrlPattern = "/index";
  // 登錄地址
  public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern;
  // 登出地址(casserver啟用service跳轉功能,需在webapps\cas\WEB-INF\cas.properties文件中啟用cas.logout.followServiceRedirects=true)
  public static final String logoutUrl = casLogoutUrl+"?service="+loginUrl;
  // 登錄成功地址
//  public static final String loginSuccessUrl = "/index";
  // 權限認證失敗跳轉地址
  public static final String unauthorizedUrl = "/error/403.html";
   
  /**
   * 實例化SecurityManager,該類是shiro的核心類
   * @return
   */
  @Bean
  public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(myShiroCasRealm());
//   <!-- 用戶授權/認證信息Cache, 采用EhCache 緩存 -->
    securityManager.setCacheManager(getEhCacheManager());
    // 指定 SubjectFactory,如果要實現cas的remember me的功能,需要用到下面這個CasSubjectFactory,并設置到securityManager的subjectFactory中
    securityManager.setSubjectFactory(new CasSubjectFactory());
    return securityManager;
  }
 
  /**
   * 配置緩存
   * @return
   */
  @Bean
  public EhCacheManager getEhCacheManager() {
    EhCacheManager em = new EhCacheManager();
    em.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
    return em;
  }
 
  /**
   * 配置Realm,由于我們使用的是CasRealm,所以已經集成了單點登錄的功能
   * @param cacheManager
   * @return
   */
  @Bean
  public MyShiroRealm myShiroCasRealm() {
    MyShiroRealm realm = new MyShiroRealm();
    // cas登錄服務器地址前綴
    realm.setCasServerUrlPrefix(ShiroConfiguration.casServerUrlPrefix);
    // 客戶端回調地址,登錄成功后的跳轉地址(自己的服務地址)
    realm.setCasService(ShiroConfiguration.shiroServerUrlPrefix + ShiroConfiguration.casFilterUrlPattern);
    // 登錄成功后的默認角色,此處默認為user角色
    realm.setDefaultRoles("user");
    return realm;
  }
 
  /**
   * 注冊單點登出的listener
   * @return
   */
  @SuppressWarnings({ "rawtypes", "unchecked" })
  @Bean
  @Order(Ordered.HIGHEST_PRECEDENCE)// 優先級需要高于Cas的Filter
  public ServletListenerRegistrationBean<?> singleSignOutHttpSessionListener(){
    ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
    bean.setListener(new SingleSignOutHttpSessionListener());
    bean.setEnabled(true);
    return bean;
  }
 
  /**
   * 注冊單點登出filter
   * @return
   */
  @Bean
  public FilterRegistrationBean singleSignOutFilter(){
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setName("singleSignOutFilter");
    bean.setFilter(new SingleSignOutFilter());
    bean.addUrlPatterns("/*");
    bean.setEnabled(true);
    return bean;
  }
 
  /**
   * 注冊DelegatingFilterProxy(Shiro)
   */
  @Bean
  public FilterRegistrationBean delegatingFilterProxy() {
    FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
    filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    // 該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理
    filterRegistration.addInitParameter("targetFilterLifecycle", "true");
    filterRegistration.setEnabled(true);
    filterRegistration.addUrlPatterns("/*");
    return filterRegistration;
  }
 
  /**
   * 該類可以保證實現了org.apache.shiro.util.Initializable接口的shiro對象的init或者是destory方法被自動調用,
   * 而不用手動指定init-method或者是destory-method方法
   * 注意:如果使用了該類,則不需要手動指定初始化方法和銷毀方法,否則會出錯
   * @return
   */
  @Bean(name = "lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }
 
  /**
   * 下面兩個配置主要用來開啟shiro aop注解支持. 使用代理方式;所以需要開啟代碼支持;
   * @return
   */
  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
    daap.setProxyTargetClass(true);
    return daap;
  }
   
  /**
   * @param securityManager
   * @return
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }
 
  /**
   * CAS過濾器
   * @return
   */
  @Bean(name = "casFilter")
  public CasFilter getCasFilter() {
    CasFilter casFilter = new CasFilter();
    casFilter.setName("casFilter");
    casFilter.setEnabled(true);
    // 登錄失敗后跳轉的URL,也就是 Shiro 執行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer驗證tiket
    casFilter.setFailureUrl(loginUrl);// 我們選擇認證失敗后再打開登錄頁面
    casFilter.setLoginUrl(loginUrl);
    return casFilter;
  }
 
  /**
   * 使用工廠模式,創建并初始化ShiroFilter
   * @param securityManager
   * @param casFilter
   * @return
   */
  @Bean(name = "shiroFilter")
  public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 必須設置 SecurityManager
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 如果不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面
    shiroFilterFactoryBean.setLoginUrl(loginUrl);
    /*
     * 登錄成功后要跳轉的連接,不設置的時候,會默認跳轉到前一步的url
     * 比如先在瀏覽器中輸入了http://localhost:8080/userlist,但是現在用戶卻沒有登錄,于是會跳轉到登錄頁面,等登錄認證通過后,
     * 頁面會再次自動跳轉到http://localhost:8080/userlist頁面而不是登錄成功后的index頁面
     * 建議不要設置這個字段
     */
//    shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);
     
    // 設置無權限訪問頁面
    shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
    /*
     * 添加casFilter到shiroFilter中,注意,casFilter需要放到shiroFilter的前面,
     * 從而保證程序在進入shiro的login登錄之前就會進入單點認證
     */
    Map<String, Filter> filters = new LinkedHashMap<>();
    filters.put("casFilter", casFilter);
     
    // logout已經被單點登錄的logout取代
    // filters.put("logout",logoutFilter());
    shiroFilterFactoryBean.setFilters(filters);
 
    loadShiroFilterChain(shiroFilterFactoryBean);
    return shiroFilterFactoryBean;
  }
 
  /**
   * 加載shiroFilter權限控制規則(從數據庫讀取然后配置),角色/權限信息由MyShiroCasRealm對象提供doGetAuthorizationInfo實現獲取來的
   * 生產中會將這部分規則放到數據庫中
   * @param shiroFilterFactoryBean
   */
  private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
    /////////////////////// 下面這些規則配置最好配置到配置文件中,注意,此處加入的filter需要保證有序,所以用的LinkedHashMap ///////////////////////
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); 
    filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter"); 
    //2.不攔截的請求
    filterChainDefinitionMap.put("/css/**","anon");
    filterChainDefinitionMap.put("/js/**","anon");
    filterChainDefinitionMap.put("/login", "anon");
    // 此處將logout頁面設置為anon,而不是logout,因為logout被單點處理,而不需要再被shiro的logoutFilter進行攔截
    filterChainDefinitionMap.put("/logout","anon");
    filterChainDefinitionMap.put("/error","anon");
    //3.攔截的請求(從本地數據庫獲取或者從casserver獲取(webservice,http等遠程方式),看你的角色權限配置在哪里)
    filterChainDefinitionMap.put("/user", "authc"); //需要登錄
    //4.登錄過的不攔截
    filterChainDefinitionMap.put("/**", "authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  }
}

部分配置參考:http://shiro.apache.org/spring.html

3、編寫Realm

由于需要集成單點登錄的功能,所以需要集成CasRealm類,該類已經為我們實現了單點認證的功能,我們要做的就是實現授權部分的功能,示例代碼如下:

?
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.chhliu.springboot.shiro.config; 
import javax.annotation.Resource; 
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.subject.PrincipalCollection;
 
import com.chhliu.springboot.shiro.mode.SysPermission;
import com.chhliu.springboot.shiro.mode.SysRole;
import com.chhliu.springboot.shiro.mode.UserInfo;
import com.chhliu.springboot.shiro.service.UserInfoService;
 
/**
 * 權限校驗核心類; 由于使用了單點登錄,所以無需再進行身份認證 只需要授權即可
 *
 * @author chhliu
 */
public class MyShiroRealm extends CasRealm {
 
  @Resource
  private UserInfoService userInfoService;
 
  /**
   * 1、CAS認證 ,驗證用戶身份
   * 2、將用戶基本信息設置到會話中,方便獲取
   * 3、該方法可以直接使用CasRealm中的認證方法,此處僅用作測試
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
 
    // 調用父類中的認證方法,CasRealm已經為我們實現了單點認證。
    AuthenticationInfo authc = super.doGetAuthenticationInfo(token);
 
    // 獲取登錄的賬號,cas認證成功后,會將賬號存起來
    String account = (String) authc.getPrincipals().getPrimaryPrincipal();
 
    // 將用戶信息存入session中,方便程序獲取,此處可以將根據登錄賬號查詢出的用戶信息放到session中
    SecurityUtils.getSubject().getSession().setAttribute("no", account);
 
    return authc;
  }
 
  /**
   * 此方法調用 hasRole,hasPermission的時候才會進行回調.
   *
   * 權限信息.(授權): 1、如果用戶正常退出,緩存自動清空; 2、如果用戶非正常退出,緩存自動清空;
   * 3、如果我們修改了用戶的權限,而用戶不退出系統,修改的權限無法立即生效。 (需要手動編程進行實現;放在service進行調用)
   * 在權限修改后調用realm中的方法,realm已經由spring管理,所以從spring中獲取realm實例, 調用clearCached方法;
   * :Authorization 是授權訪問控制,用于對用戶進行的操作授權,證明該用戶是否允許進行當前操作,如訪問某個鏈接,某個資源文件等。
   *
   * @param principals
   * @return
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    System.out.println("權限配置-->MyShiroRealm.doGetAuthorizationInfo()");
 
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    // 獲取單點登陸后的用戶名,也可以從session中獲取,因為在認證成功后,已經將用戶名放到session中去了
    String userName = (String) super.getAvailablePrincipal(principals);
//       principals.getPrimaryPrincipal(); 這種方式也可以獲取用戶名
 
    // 根據用戶名獲取該用戶的角色和權限信息
    UserInfo userInfo = userInfoService.findByUsername(userName);
 
    // 將用戶對應的角色和權限信息打包放到AuthorizationInfo中
    for (SysRole role : userInfo.getRoleList()) {
      authorizationInfo.addRole(role.getRole());
      for (SysPermission p : role.getPermissions()) {
        authorizationInfo.addStringPermission(p.getPermission());
      }
    }
 
    return authorizationInfo;
  }
}

下面,我們就可以進行驗證測試了!

在瀏覽器輸入http:127.0.1.28:8080/userInfo/userList 我們會發現,會自動跳轉到單點的登錄頁面

spring boot整合Shiro實現單點登錄的示例代碼

然后我們輸入用戶名和密碼,就會自動跳轉到http:127.0.1.28:8080/userInfo/userList頁面了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/liuchuanhong1/article/details/76850181

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 在线亚洲一区 | 精品久久av | av电影一区| 九九综合九九 | 精品无人乱码一区二区三区的优势 | 在线国产视频观看 | 国产日韩欧美综合 | 成人看的免费视频 | 日本一区二区三区在线视频 | 亚洲免费视频一区二区 | 欧美一区二区三区男人的天堂 | 日韩一区二区三区视频 | 午夜影晥 | 精品福利视频网站 | 日韩国产一区二区三区 | 亚洲精品h | 韩日中文字幕 | 国产目拍亚洲精品99久久精品 | 午夜视频在线观看网站 | av电影资源| 99亚洲伊人久久精品影院红桃 | 亚洲国产精品一区二区第一页 | 中文字幕日韩欧美一区二区三区 | 成人黄色小视频 | 亚洲日本在线观看视频 | 亚洲大片 | 黄色成人在线观看视频 | 亚洲综合色自拍一区 | 成人免费视频在线观看 | 成人av一区二区三区 | 久久免费视频3 | 国产综合精品一区二区三区 | 精品久久久久久久久久久 | 亚洲欧洲av| 国产精品久久久久久久久久免费 | 中文字幕在线免费视频 | 国产成人一区二区三区 | 91免费观看 | 亚洲精品福利 | 成人av电影天堂 | 国产在线精品一区二区 |