SpringBoot入門,SpringSecurity入門

 2023-10-17 阅读 29 评论 0

摘要:Spring Security介紹: Spring Security 的前身是 Acegi Security ,是 Spring 項目組中用來提供安全認證服務的框架。 (https://projects.spring.io/spring-security/) Spring Security 為基于J2EE企業應用軟件提供了全面安全服務。特別 是使用領先的J2EE解決方案-Sprin

Spring Security介紹:
Spring Security 的前身是 Acegi Security ,是 Spring 項目組中用來提供安全認證服務的框架。
(https://projects.spring.io/spring-security/) Spring Security 為基于J2EE企業應用軟件提供了全面安全服務。特別
是使用領先的J2EE解決方案-Spring框架開發的企業軟件項目。人們使用Spring Security有很多種原因,不過通常吸
引他們的是在J2EE Servlet規范或EJB規范中找不到典型企業應用場景的解決方案。 特別要指出的是他們不能再
WAR 或 EAR 級別進行移植。這樣,如果你更換服務器環境,就要,在新的目標環境進行大量的工作,對你的應用
系統進行重新配 置安全。使用Spring Security 解決了這些問題,也為你提供很多有用的,完全可以指定的其他安
全特性。 安全包括兩個主要操作。

  • “認證”,是為用戶建立一個他所聲明的主體。主題一般式指用戶,設備或可以在你系 統中執行動作的其他系統。
  • “授權”指的是一個用戶能否在你的應用中執行某個操作,在到達授權判斷之前,身份的主題已經由 身份驗證過程建立了。

使用步驟

  1. 導入Maven依賴
<dependencies><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>5.0.1.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>5.0.1.RELEASE</version></dependency>
</dependencies>

  1. web.xml
<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>
  • 注意 < filter-name >springSecurityFilterChain< /filter-name >是固定寫法

  1. spring security配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:security="http://www.springframework.org/schema/security"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security.xsd"><!-- 配置不攔截的資源 --><security:http pattern="/login.jsp" security="none"/><security:http pattern="/failer.jsp" security="none"/><security:http pattern="/css/**" security="none"/><security:http pattern="/img/**" security="none"/><security:http pattern="/plugins/**" security="none"/><!--配置具體的規則auto-config="true"	不用自己編寫登錄的頁面,框架提供默認登錄頁面use-expressions="false"	是否使用SPEL表達式(沒學習過)--><security:http auto-config="true" use-expressions="false"><!-- 配置具體的攔截的規則 pattern="請求路徑的規則" access="訪問系統的人,必須有ROLE_USER的角色" --><security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/><!-- 定義跳轉的具體的頁面 --><security:form-loginlogin-page="/login.jsp"login-processing-url="/login.do"default-target-url="/index.jsp"authentication-failure-url="/failer.jsp"authentication-success-forward-url="/pages/main.jsp"/><!-- 關閉跨域請求 --><security:csrf disabled="true"/><!-- 退出 --><security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp" /></security:http><!-- 切換成數據庫中的用戶名和密碼 --><security:authentication-manager><security:authentication-provider user-service-ref="userService"><!-- 配置加密的方式--><security:password-encoder ref="passwordEncoder"/></security:authentication-provider></security:authentication-manager><!-- 配置加密類 --><bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/><!-- 提供了入門的方式,在內存中存入用戶名和密碼<security:authentication-manager><security:authentication-provider><security:user-service><security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/></security:user-service></security:authentication-provider></security:authentication-manager>-->
</beans>

Spring Security使用數據庫認證

在Spring Security中如果想要使用數據進行認證操作,有很多種操作方式,這里我們介紹使用UserDetails、UserDetailsService來完成操作。

  • UserDetails
public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();boolean isAccountNonExpired();boolean isAccountNonLocked();boolean isCredentialsNonExpired();boolean isEnabled();
}

UserDetails是一個接口,我們可以認為UserDetails作用是于封裝當前進行認證的用戶信息,但由于其是一個接口,所以我們可以對其進行實現,也可以使用Spring Security提供的一個UserDetails的實現類User來完成操作
以下是User類的部分代碼

public class User implements UserDetails, CredentialsContainer {private String password;private final String username;private final Set<GrantedAuthority> authorities;private final boolean accountNonExpired; //帳戶是否過期private final boolean accountNonLocked; //帳戶是否鎖定private final boolean credentialsNonExpired; //認證是否過期private final boolean enabled; //帳戶是否可用
  • UserDetailsService
public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

用戶登錄

  • spring security的配置
<security:authentication-manager><!--userService為 Service層實現類的Bean名稱 --><security:authentication-provider user-service-ref="userService"><!-- 配置加密的方式<security:password-encoder ref="passwordEncoder"/>--></security:authentication-provider>
</security:authentication-manager>
  • Service代碼
    Service 需要繼承UserDetailsService
public interface UserService extends UserDetailsService{
}//UserServiceImpl代碼
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;UserInfo userInfo = null;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {try {userInfo = userDao.findByUsername(s);} catch (Exception e) {e.printStackTrace();}User user = new User(userInfo.getUsername(), "{noop}" + userInfo.getPassword(),userInfo.getStatus() == 0 ? false : true, true, true, true, getAuthority(userInfo.getRoles()));return user;}private List<SimpleGrantedAuthority> getAuthority(List<Role> roleList) {List<SimpleGrantedAuthority> list = new ArrayList<>();for (Role role : roleList) {list.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));}return list;}@Overridepublic List<UserInfo> findAll() throws Exception {return userDao.findAll();}
}

用戶退出

使用spring security完成用戶退出,非常簡單

  • 配置
<security:logout invalidate-session="true" logout-url="/logout.do" logout-success-
url="/login.jsp" />
  • 頁面中
<a href="${pageContext.request.contextPath}/logout.do"
class="btn btn-default btn-flat">注銷</a>

權限控制

服務器端方法級權限控制

SpringBoot入門?在服務器端我們可以通過Spring security提供的注解對方法來進行權限控制。Spring Security在方法的權限控制上支持三種類型的注解,JSR-250注解、@Secured注解和支持表達式的注解,這三種注解默認都是沒有啟用的,需要單獨通過global-method-security元素的對應屬性進行啟用

開啟注解使用

  • 配置文件開啟
<!--JSR-250注解-->
<security:global-method-security jsr250-annotations="enabled"/>
<!--@Secured注解-->
<security:global-method-security secured-annotations="enabled"/>
<!--支持表達式的注解-->
<security:global-method-security pre-post-annotations="disabled"/>
  • 注解開啟
    @EnableGlobalMethodSecurity :Spring Security默認是禁用注解的,要想開啟注解,需要在繼承WebSecurityConfigurerAdapter的類上加@EnableGlobalMethodSecurity注解,并在該類中將AuthenticationManager定義為Bean。
JSR-250注解

使用需要導入依賴

<dependency><groupId>javax.annotation</groupId><artifactId>jsr250-api</artifactId><version>1.0</version>
</dependency>
  • @RolesAllowed表示訪問對應方法時所應該具有的角色

示例:

@RolesAllowed({“USER”, “ADMIN”}) 該方法只要具有"USER", "ADMIN"任意一種權限就可以訪問。這里可以省略前綴ROLE_,實際的權限可能是ROLE_ADMIN

  • @PermitAll表示允許所有的角色進行訪問,也就是說不進行權限控制
  • @DenyAll是和PermitAll相反的,表示無論什么角色都不能訪問\
支持表達式的注解
  • @PreAuthorize 在方法調用之前,基于表達式的計算結果來限制對方法的訪問

Spring 框架。示例:

@PreAuthorize("#userId == authentication.principal.userId or hasAuthority(‘ADMIN’)")
void changePassword(@P(“userId”) long userId ){ }
這里表示在changePassword方法執行之前,判斷方法參數userId的值是否等于principal中保存的當前用戶的userId,或者當前用戶是否具有ROLE_ADMIN權限,兩種符合其一,就可以訪問該方法。

  • @PostAuthorize 允許方法調用,但是如果表達式計算結果為false,將拋出一個安全性異常

示例:

@PostAuthorize
User getUser(“returnObject.userId == authentication.principal.userId or
hasPermission(returnObject, ‘ADMIN’)”);

  • @PostFilter 允許方法調用,但必須按照表達式來過濾方法的結果
  • @PreFilter 允許方法調用,但必須在進入方法之前過濾輸入值

Spring Security允許我們在定義URL訪問或方法訪問所應有的權限時使用Spring EL表達式,在定義所需的訪問權限時如果對應的表達式返回結果為true則表示擁有對應的權限,反之則無。Spring Security可用表達式對象的基類是SecurityExpressionRoot,其為我們提供了如下在使用Spring EL表達式對URL或方法進行權限控制時通用的內置表達式。

表達式描述
hasRole([role])當前用戶是否擁有指定角色。
hasAnyRole([role1,role2])多個角色是一個以逗號進行分隔的字符串。如果當前用戶擁有指定角色中的任意一個則返回true。
hasAuthority([auth])等同于hasRole
hasAnyAuthority([auth1,auth2])等同于hasAnyRole
Principle代表當前用戶的principle對象
authentication直接從SecurityContext獲取的當前Authentication對象
permitAll總是返回true,表示允許所有的
denyAll總是返回false,表示拒絕所有的
isAnonymous()當前用戶是否是一個匿名用戶
isRememberMe()表示當前用戶是否是通過Remember-Me自動登錄的
isAuthenticated()表示當前用戶是否已經登錄認證成功了。
isFullyAuthenticated()如果當前用戶既不是一個匿名用戶,同時又不是通過Remember-Me自動登錄的,則返回true。
@Secured注解
  • @Secured注解標注的方法進行權限控制的支持,其值默認為disabled。

springboot入門項目?示例:

@Secured(“IS_AUTHENTICATED_ANONYMOUSLY”)
public Account readAccount(Long id);
@Secured(“ROLE_TELLER”)

  • 注意 ROLE_前綴不能省略

頁面端標簽控制權限

在jsp頁面中我們可以使用spring security提供的權限標簽來進行權限控制

  • maven導入
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-taglibs</artifactId><version>version</version>
</dependency>
  • 頁面導入
<%@taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
常用標簽

在jsp中我們可以使用以下三種標簽,其中authentication代表的是當前認證對象,可以獲取當前認證對象信息,例如用戶名。其它兩個標簽我們可以用于權限控制

authentication

<security:authentication property="" htmlEscape="" scope="" var=""/>
  • property: 只允許指定Authentication所擁有的屬性,可以進行屬性的級聯獲取,如“principle.username”,不允許直接通過方法進行調用
  • htmlEscape:表示是否需要將html進行轉義。默認為true。
  • scope:與var屬性一起使用,用于指定存放獲取的結果的屬性名的作用范圍,默認pageContext。Jsp中擁有的作用范圍都進行進行指定
  • var: 用于指定一個屬性名,這樣當獲取到了authentication的相關信息后會將其以var指定的屬性名進行存放,默認是存放在pageConext中

Spring入門,authorize

authorize是用來判斷普通權限的,通過判斷用戶是否具有對應的權限而控制其所包含內容的顯示

<security:authorize access="" method="" url="" var=""></security:authorize>
  • access: 需要使用表達式來判斷權限,當表達式的返回結果為true時表示擁有對應的權限
  • method:method屬性是配合url屬性一起使用的,表示用戶應當具有指定url指定method訪問的權限,
  • method的默認值為GET,可選值為http請求的7種方法
  • url:url表示如果用戶擁有訪問指定url的權限即表示可以顯示authorize標簽包含的內容
  • var:用于指定將權限鑒定的結果存放在pageContext的哪個屬性中

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/143599.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息