SpringSecurity安全框架和Bcrypt加密
阿新 • • 發佈:2018-12-11
SpringSecurity開發步驟
Spring Security是一個能夠為基於Spring的企業應用系統提供宣告式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面程式設計)功能,為應用系統提供宣告式的安全訪問控制功能,減少了為企業系統安全控制編寫大量重複程式碼的工作
1.開發思路
1. 攔截使用者請求 登入頁的路徑為("../login" method="post") 2. 當前登陸的使用者是誰? 3. 配置訪問某一個資源需要什麼角色? 4. 當前登陸使用者具有什麼角色? 5. 認證/登陸 授權
2.開發步驟
1.第一步: 引入依賴(spring + spring security)
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
< artifactId>spring-security-config</artifactId>
</dependency>
2.配置web.xml檔案(spring配置檔案 + DelegatingFilterProxy-委託代理過濾器)
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- 載入spring的核心配置檔案 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 配置一個攔截器 -->
<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>
</web-app>
3.配置spring配置檔案
<?xmlversion="1.0"encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- security="none"設定此資源不被攔截 -->
<http pattern="/login.html"security="none"></http>
<http pattern="/css/**"security="none"></http>
<http pattern="/img/**"security="none"></http>
<http pattern="/js/**"security="none"></http>
<http pattern="/plugins/**"security="none"></http>
<!-- 頁面攔截規則 -->
<!--
1. http : 表示頁面的攔截規則
2. intercept-url: 表示攔截的頁面
/* 表示的是該目錄下的資源,只包括本級目錄不包括下級目錄
/** 表示的是該目錄以及該目錄下所有級別子目錄的資源
use-expressions為是否使用使用 Spring 表示式語言(SpEL),預設為true ,如果開啟
3. form-login: 表示開啟表單登陸功能
3.1 login-page: 登陸頁
3.2 default-target-url: 登陸成功後預設跳轉的頁面
3.3 authentication-failure-url: 登陸失敗預設跳轉的頁面
3.4 csrf disabled="true"關閉csrf ,如果不加會出現錯誤
3.5 always-use-default-target: 指定了是否在身份驗證通過後總是跳轉到default-target-url屬性指定的URL
3.6 logout : 登出操作
logout-url : 退出的地址,預設的地址為 /logout
logout-success-url: 預設為 index.html
4. authentication-manager: 認證管理器, 判斷使用者需要什麼樣的角色
user-service-ref: 全類名(該類實現了UserDetailsService介面)
-->
<http use-expressions="false">
<!-- 當前使用者必須有ROLE_USER的角色 才可以訪問根目錄及所屬子目錄的資源 -->
<intercept-url pattern="/**" access="ROLE_SELLER"/>
<!--<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>-->
<form-login login-page="/login.html" default-target-url="/admin/index.html"
authentication-failure-url="/login.html"
always-use-default-target="true"/>
<csrf disabled="true"/>
<headers>
<frame-optionspolicy="SAMEORIGIN"/>
</headers>
<logout logout-url="" logout-success-url=""/>
</http>
<!-- 認證管理器 -->
<authentication-manager>
<!-- 引入認證類 -->
<authentication-provider user-service-ref="userDetailService">
<password-encoder ref="bcryptEncoder"></password-encoder>
</authentication-provider>
</authentication-manager>
<!-- 認證類 -->
<beans:bean id="userDetailService" class="com.oranges.service.UserDetailsServiceImpl">
<!-- 依賴注入遠端的服務 -->
<beans:property name="sellerService" ref="sellerService"></beans:property>
</beans:bean>
<!-- 引用dubbo 服務 -->
<dubbo:application name="pinyougou-shop-web" />
<dubbo:registry address="zookeeper://192.168.25.135:2181"/>
<dubbo:reference id="sellerService"
interface="com.oranges.sellergoods.service.SellerService"></dubbo:reference>
<beans:bean id="bcryptEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
</beans:bean>
</beans:beans>
4.前端頁面的表單提交方式
<!-- 提交路徑必須為 login, 提交方式必須為post -->
<form action="../login" method="post">
</form>
5.獲取通過框架登陸後登陸者的姓名
@RestController
@RequestMapping("/login")
publicclassLoginController {
@RequestMapping("name")
publicMap name(){
String name=SecurityContextHolder.getContext()
.getAuthentication().getName();
Mapmap=newHashMap();
map.put("loginName", name);
returnmap ;
}
}
6.編輯後臺程式碼認證類
/**
* 認證類
*/
public class UserDetailsServiceImpl implements UserDetailsService {
// 呼叫遠端的服務, 這裡沒有配置包掃描, 採用配置檔案的方式進行注入
private SellerService sellerService;
public void setSellerService(SellerService sellerService) {
this.sellerService = sellerService;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("經過了UserDetailsServiceImpl");
//構建角色列表
List<GrantedAuthority> grantAuths=new ArrayList();
grantAuths.add(new SimpleGrantedAuthority("ROLE_SELLER"));
// 查詢資料庫得到 使用者物件
TbSeller seller = sellerService.findOne(username);
if(seller!=null){
// 判斷使用者的狀態
if(seller.getStatus().equals("1")){
//grantAuths 使用者所具有的角色
return new User(username,seller.getPassword(),grantAuths);
}else{
return null;
}
}else{
return null;
}
}
}
6.登出登陸
<logout logout-url="" logout-success-url=""/>
<!-- 前臺頁面的提交路徑為 "../logout" -->
3.密碼加密: BCrypt
1.瞭解
使用者表的密碼通常使用MD5等不可逆演算法加密後儲存,為防止彩虹表破解更會先使用一個特定的字串(如域名)加密,然後再使用一個隨機的salt(鹽值)加密。特定字串是程式程式碼中固定的,salt是每個密碼單獨隨機,一般給使用者表加一個欄位單獨儲存,比較麻煩。BCrypt演算法將salt隨機並混入最終加密後的密碼,驗證時也無需單獨提供之前的salt,從而無需單獨處理salt問題。
2.加密實現: BCryptPasswordEncoder
@RequestMapping("/add")
public Result add(@RequestBodyTbSeller seller){
//密碼加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode(seller.getPassword());
seller.setPassword(password);
try{
sellerService.add(seller);
returnnew Result(true,"增加成功");
}catch(Exception e){
e.printStackTrace();
returnnew Result(false,"增加失敗");
}
}
3.spring檔案的配置: 告訴系統該密碼是以什麼樣子的形式加密的
<beans:bean id="bcryptEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!-- 認證管理器 -->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref='userDetailService'>
<password-encoder ref="bcryptEncoder"></password-encoder>
</authentication-provider>
</authentication-manager>