1:導入Spring Security環(huán)境
(1)pom.xml中添加依賴
(2)web.xml添加代理過濾器
2:實現認證和授權
(1)認證:SpringSecurityUserService.java
(2)創(chuàng)建Service類、Dao接口類、Mapper映射文件
(3)springmvc.xml(dubbo注解掃描范圍擴大)
(4)spring-security.xml
(5)springmvc.xml(導入spring-security.xml)
(6)TravelItemController類(@PreAuthorize("hasAuthority('CHECKITEM_ADD')"):完成權限)
(7)travelitem.html(如果沒有權限,可以提示錯誤信息)
(8)導入login.html測試登錄
3:顯示用戶名
4:用戶退出
1.1導入Spring Security環(huán)境
【路徑】
1:pom.xml導入坐標
2:web.xml添加代理過濾器
1.1.1.第一步:pom.xml導入坐標
在父工程的pom.xml中導入Spring Security的maven坐標
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
1.1.2.第二步:web.xml添加代理過濾器
在meinian_web工程的web,xml文件中配置用于整合Spring Security框架的過濾器DelegatingFilterProxy
<filter>
<!--
DelegatingFilterProxy用于整合第三方框架(代理過濾器,非真正的過濾器,真正的過濾器需要在spring的配置文件)
整合Spring Security時過濾器的名稱必須為springSecurityFilterChain,
否則會拋出NoSuchBeanDefinitionException異常
-->
<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>
1.1.3.第三步:sql語句
#1 使用登錄名查詢用戶信息
SELECT * FROM t_user WHERE username='admin'
#2 傳遞用戶id查詢角色合集
SELECT r.* FROM t_role r, t_user_role ur WHERE ur.role_id = r.id AND ur.user_id=1
# 傳遞角色id查詢權限集合
SELECT p.* FROM t_permission p, t_role_permisson rp WHERE p.id = rp.permission_id AND rp.role_id = 1
實現認證和授權
1.2.1.第一步:SpringSecurityUserService.java
在meinian_web工程中按照Spring Security框架要求提供SpringSecurityUserService,并且實現UserDetailsSercice接口
package com.atguigu.security;
import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.pojo.Permission;
import com.atguigu.pojo.Role;
import com.atguigu.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
@Component
public class SpringSecurityUserService implements UserDetailsService {
@Reference
UserService userService; // 遠程調用
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1.查詢用戶信息,以及用戶對應的角色,以及角色對應的權限
com.atguigu.pojo.User user = userService.findUserByUserName(username);
if (user==null){
// 不存在這個用戶
return null;// 返回null給框架,框架會拋異常處理,跳轉到登錄頁面
}
// 2.構建權限集合
Set<GrantedAuthority> authorities = new HashSet<>();
Set<Role> roles = user.getRoles(); //集合數據 由RoleDao幫忙方法來查詢得到的
for (Role role : roles) {
Set<Permission> permissions = role.getPermissions(); // 集合數據 有 PermissionDao幫忙方法查詢得到的
for (Permission permission : permissions) {
authorities.add(new SimpleGrantedAuthority(permission.getKeyword()));
}
}
org.springframework.security.core.userdetails.User securityUser =
new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
return securityUser; // 框架提供的User實現了UserDetails接口
}
}
1.2.2.第二步:Service、Dao接口、Mapper映射文件
創(chuàng)建UserService服務接口、服務實現類、Dao接口、Mapper映射文件
【路徑】
1:UserService.java 接口
2:UserServiceImpl.java 類
3:UserDao.java(使用用戶id查詢用戶)
4:RoleDao.java (使用用戶id查詢角色集合)
5:PermissionDao.java(使用角色id查詢權限集合)
6:UserDao.xml(使用用戶id查詢用戶)
7:RoleDao.xml(使用用戶id查詢角色集合)
8:PermissionDao.xml (使用角色id查詢權限集合)
使用debug跟蹤調試,查看user

1.2.3.第三步:springmvc.xml
修改meinian_web工程中的springmvc.xml文件,修改dubbo批量掃描的包路徑
之前的掃描包
<!--批量掃描 -->
<dubbo:annotation package="com.atguigu.controller" />
現在的掃描包
<!--批量掃描, 范圍要變大,不然掃描不到SpringSecurityUserService包-->
<dubbo:annotation package="com.atguigu" />
注意:
此處原來掃描的包為com.atguigu.controller,現在改為com.atguigu包的目的是需要將我們上面定義的SpringSecurityUserService也掃描到,因為在SpringSecurityUserService的loadUserByUsername方法中需要通過dubbo遠程調用名稱為UserService的服務
1.2.4.第四步:spring-security.xml
【路徑】
1:定義哪些鏈接可以放行
2:定義哪些鏈接不可以方向,即需要有角色、權限才可以放行
3:認證管理,定義登錄賬號和密碼,并授權訪問的角色、權限
4:設置在頁面可以通過iframe訪問受保護的頁面,默認為不允許默認訪問,需要添加security:frame-optionspolicy=”SAMEORIGIN“
【講解】
在meinian_web工程中提供spring-security.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!--靜態(tài)資源放行 對css不做權限判斷-->
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/img/**"/>
<security:http security="none" pattern="/js/**"/>
<!-- <security:http security="none" pattern="/pages/**"/>-->
<security:http security="none" pattern="/template/**"/>
<security:http security="none" pattern="/plugins/**"/>
<security:http security="none" pattern="/login.html"/>
<!-- 對控制器中的方法提供注解的權限驗證-->
<security:global-method-security pre-post-annotations="enabled"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/pages/**" access="isAuthenticated()"/>
<security:form-login login-page="/login.html"
login-processing-url="/login.do"
username-parameter="username"
password-parameter="password"
default-target-url="/pages/main.html"
always-use-default-target="true"
authentication-failure-forward-url="/login.html"
/>
<!--禁用csrf的獲取使用-->
<security:csrf disabled="true"/>
<security:logout logout-success-url="/login.html" logout-url="/logout.do" invalidate-session="true"/>
<security:headers>
<!--設置在頁面可以通過iframe訪問受保護的頁面,默認為不允許訪問-->
<security:frame-options policy="SAMEORIGIN"/>
</security:headers>
<security:access-denied-handler ref="customAccessDeniedHandler"/>
</security:http>
<!--認證authentication(登錄)-->
<security:authentication-manager>
<!--使用userServiceImpl進行登錄-->
<security:authentication-provider user-service-ref="userServiceImpl">
<security:password-encoder ref="bcry"/>
</security:authentication-provider>
</security:authentication-manager>
<bean id="bcry" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans>
在spring-security.xml中添加
放置到 <security:http auto-config="true" use-expressions="true"> 里面
<security:headers>
<!--設置在頁面可以通過iframe訪問受保護的頁面,默認為不允許訪問-->
<security:frame-options policy="SAMEORIGIN"/>
</security:headers>
因為我們在main.html中定義: 如果不配置springSecurity 會認為iframe訪問的html頁面時受保護的頁面,不允許訪問。
1.2.5.第五步: springmvc.xml
在springmvc,xml文件中引入spring-security.xml文件
<import resource="spring-security.xml"/>
1.2.6.第六步: TravelItemController 類 授權
在Controller的方法上加入權限 控制注解,此處以TravelItemController為例
@RequestMapping("/update")
@PreAuthorize("hasAuthority('TRAVELITEM_EDIT')") // 權限校驗
public Result update(@RequestBody TravelItem travelItem){
try {
travelItemService.update(travelItem);
return new Result(true, MessageConstant.EDIT_TRAVELITEM_SUCCESS);
} catch (Exception e) {
e.printStackTrace();
return new Result(false, MessageConstant.EDIT_TRAVELITEM_FAIL);
}
}
1.2.7第七步: CustomAccessDeniedHandler類
添加頁面,沒有權限時提示信息設置
1.在<security:http>標簽中增加<security:access-denied-handler>
<!-- 自定義異常處理類 -->
<security:access-denied-handler ref="customAccessDeniedHandler"/>
2.增加自定義處理類
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
if (isAjaxRequest(request)) {// AJAX請求,使用response發(fā)送403
Result result = new Result(false, "無權訪問","403");
String json = JSON.toJSONString(result);
response.getWriter().print(json);// 不要使用prinln方法,含有回車換行符
} else{// 同步請求處理
request.getRequestDispatcher("/pages/error/403.html").forward(request,response);
}
}
/**
* 判斷是否為ajax請求
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
if (request.getHeader("accept").indexOf("application/json") > -1
|| (request.getHeader("X-Requested-With") != null
&& request.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest"))) {
return true;
}
return false;
}
3.增加/pages/error/403.html頁面
1.2.8.第八步: 導入login.html頁面
1.3.顯示用戶名
【路徑】
1:引入js
2:定義username屬性
3:使用鉤子函數,調用ajax,查詢登錄用戶(從SpringSecurity中獲取),復制username屬性
4:修改頁面,使用{username}顯示用戶信息
【講解】
前面我們已經完成了認證和授權操作,如果用戶認證成功后需要在頁面顯示當前用戶的用戶名,Spring Security在認證成功后會將用戶信息保存到框架提供的上下文對象中,所以此處我們就可以調用Spring Security框架提供的api獲取當前用戶的username 并展示到頁面上
實現步驟:
第一步:在mian.html頁面中修改,定義username模型數據基于VUE的數據展示用戶名,發(fā)送Ajax請求獲取username
(1):引入js
<scipt src ="../js/axios-0.18.0.js">
(2):定義username屬性
(3):使用鉤子函數,調用ajax
(4):修改頁面
顯示當前登錄人
1.4用戶退出
【路徑】
1:在main,html中提供的退出菜單上加入超鏈接
2:在Spring-security.xml文件中配置
【講解】
第一步:在main.html中提供的退出菜單上加入超鏈接
<el-dropdown-item divided>
<span style="display:block;"><a href="/logout.do">退出</a></span>
</el-dropdown-item>
第二步:在Spring-security.xml文件中配置
<security:logout logout-url="/logout.do" logout-success-url="/login.html" invalidate-session="true"/>