1.在pom.xml加入SpringSecurity的依賴
<!-- SpringSecurity對Web應用進行權限管理 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<!-- SpringSecurity配置 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<!-- SpringSecurity標簽庫 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
2.在web.xml加入springsecurity 的過濾器配置
<!-- springsecurity 的過濾器配置 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.撰寫一個配置類WebAppSecurityConfig,該類要繼承WebSecurityConfigurerAdapter
//表示當前類是一個配置類 @Configuration //啟用web環境下權限配置功能 @EnableWebSecurity public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter{ }
4.在配置類中實作兩個方法protected void configure(HttpSecurity security),configure(AuthenticationManagerBuilder builder),
@Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { // 裝配userDetailsService物件 builder .userDetailsService(userDetailsService).passwordEncoder(getBCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity security) throws Exception { // 準備JdbcTokenRepositoryImpl物件 JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl(); tokenRepository.setDataSource(dataSource); // 創建資料庫表 tokenRepository.setCreateTableOnStartup(true); tokenRepository.initDao(); security .authorizeRequests() // 對請求進行授權 .antMatchers("/index.jsp") // 針對/index.jsp路徑進行授權 .permitAll() // 可以無條件訪問 .antMatchers("/layui/**") // 針對/layui目錄下所有資源進行授權 .permitAll() // 可以無條件訪問 .antMatchers("/level1/**") // 針對/level1/**路徑設定訪問要求 .hasRole("學徒") // 要求用戶具備“學徒”角色才可以訪問 .antMatchers("/level2/**") // 針對/level2/**路徑設定訪問要求 .hasAuthority("內門弟子") // 要求用戶具備“內門弟子”權限才可以訪問 .and() .authorizeRequests() // 對請求進行授權 .anyRequest() // 任意請求 .authenticated() // 需要登錄以后才可以訪問 .and() .formLogin() // 使用表單形式登錄 // 關于loginPage()方法的特殊說明 // 指定登錄頁的同時會影響到:“提交登錄表單的地址”、“退出登錄地址”、“登錄失敗地址” // /index.jsp GET - the login form 去登錄頁面 // /index.jsp POST - process the credentials and if valid authenticate the user 提交登錄表單 // /index.jsp?error GET - redirect here for failed authentication attempts 登錄失敗 // /index.jsp?logout GET - redirect here after successfully logging out 退出登錄 .loginPage("/index.jsp") // 指定登錄頁面(如果沒有指定會訪問SpringSecurity自帶的登錄頁) // loginProcessingUrl()方法指定了登錄地址,就會覆寫loginPage()方法中設定的默認值/index.jsp POST .loginProcessingUrl("/do/login.html") // 指定提交登錄表單的地址 .usernameParameter("loginAcct") // 定制登錄賬號的請求引數名 默認為username .passwordParameter("userPswd") // 定制登錄密碼的請求引數名 默認為password .defaultSuccessUrl("/main.html") // 登錄成功后前往的地址 .and() .csrf() .disable() // 禁用CSRF功能 .logout() // 開啟退出功能 .logoutUrl("/do/logout.html") // 指定處理退出請求的URL地址 .logoutSuccessUrl("/index.jsp") // 退出成功后前往的地址 .and() .exceptionHandling() // 指定例外處理器 // .accessDeniedPage("/to/no/auth/page.html") // 訪問被拒絕時前往的頁面 .accessDeniedHandler(new AccessDeniedHandler() { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { request.setAttribute("message", "抱歉!您無法訪問這個資源!☆☆☆"); request.getRequestDispatcher("/WEB-INF/views/no_auth.jsp").forward(request, response); } }) .and() .rememberMe() // 開啟記住我功能 .tokenRepository(tokenRepository) // 裝配token倉庫 ; }
5.在啟動時會報一個錯誤
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' available
原因:
三大組件啟動順序:
首先:ContextLoaderListener初始化,創建Spring的IOC容器
其次:DelegatingFilterProxy初始化,查找IOC容器,查找Bean
最后:DispatcherServlet初始化,創建SpringMVC的IOC容器
專案啟動程序中,先進行ContextLoaderListener初始化加載spring組態檔生成springIOC容器,然后加載過濾器Filter,加載到DelegatingFilterProxy時需要在IOC容器中找一個SpringSecurityFilterChain的bean(默認會去Spring的IOC容器中去找),最后DispatcherServlet初始化加載SpringMvc組態檔生成SpringMVC的IOC容器,為了讓SpringSecurity對瀏覽器請求進行權限控制,需要讓SpringMVC來掃描WebAppSecurityConfig,所以DelegatingFilterProxy需要的bean在SpringMvc的IOC容器中,導致找不到這個Bean,
解決辦法:
方法一.讓SpringMVC的IOC容器和Spring的IOC容器合并,全部用DispatcherServlet來加載所有組態檔,
具體做法:
①在web.xml檔案中注釋掉監聽器ContextLoaderListener的配置
②在springmvc組態檔中加載spring組態檔
<!-- 匯入其他組態檔 -->
<import resource="classpath:application*.xml"/>
方法二:修改原始碼
具體做法:
1.初始化時直接跳過查找IOC容器
①創建org.springframework.web.filter包,在這個包下創建類DelegatingFilterProxy,將原始碼拷貝過來,
按住Ctrl點擊<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>,進入原始碼,拷貝出來,
<!-- springsecurity 的過濾器配置 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
②去230行注釋掉初始化查找IOC的代碼
// Fetch Spring root application context and initialize the delegate early, // if possible. If the root application context will be started after this // filter proxy, we'll have to resort to lazy initialization. // WebApplicationContext wac = findWebApplicationContext(); // if (wac != null) { // this.delegate = initDelegate(wac); // }
2.第一次加載時去找SpringMVC的IOC容器
①在DelegatingFilterProxy類251行左右進行如下修改
//查找IOC容器,優先選擇SpringIOC容器,注釋掉,自己寫 //WebApplicationContext wac = findWebApplicationContext(); //1.獲取ServletContext物件 ServletContext sc = this.getServletContext(); //2.拼接SpringMVC將IOC容器存入ServletContext域的時候使用的屬性名 String servletName = "springDispatcherServlet"; String attrName =FrameworkServlet.SERVLET_CONTEXT_PREFIX+servletName; //3.根據attrName從servletContext域中獲取IOC容器 WebApplicationContext wac = (WebApplicationContext) sc.getAttribute(attrName);
最后啟動服務就大功告成了!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/469450.html
標籤:Java
