黑莲技术资源论坛

作者: 顺势而为47
查看: 78|回复: 0

「Spring Boot 集成應用」Spring Security集成整合配置使用

「Spring Boot 集成應用」Spring Security集成整合配置使用

[复制链接]
顺势而为47 | 显示全部楼层 发表于: 2022-9-22 09:02:53
顺势而为47 发表于: 2022-9-22 09:02:53 | 显示全部楼层 |阅读模式
查看: 78|回复: 0
1. Spring Security 簡介

Spring Security 是一種基于 Spring AOP 和 Servlet 過濾器的安全框架。原名Acegi Security,最早于2003年起源于Spring社區。 2007年末正式歸為Spring Framework的正式子項目,並改名為Spring Security 。此後, Spring Security有了長遠發展,現已成為一款基于Spring Framework的廣泛應用的安全框架,主要為應用服務提供用戶認證(Authentication)和用戶授權(Authorization)功能。詳情可參考Spring Security 官方文檔。
Spring Security 針對安全方面的兩大難題, 鑒權(Authentication)和授權(Authorization)提供了靈活強大的解決方案。

  • 用戶鑒權(Authentication), 是指對用戶身份的鑒權, 驗證某個用戶是否為系統中的合法對象, 是否能夠訪問對應的系統資源。比如用戶輸入賬戶和密碼登陸系統。
  • 用戶授權(Authorization),是指授予通過認證的用戶指定的系統資源操作權限, 能否執行具體某個操作。比如用戶能夠訪問操作的菜單,能夠請求的功能接口, 這些都是系統資源。
Spring Security優勢︰

  • 靈活性, Spring Security並不局限于Spring MVC,雖然它是基于Spring Framework實現的,但它並不依賴于Spring MVC,可以獨立于MVC應用在其他Java EE框架之上。
  • 功能強大,Spring Security的安全管制並不只限制于Web請求,除此之外它還可以針對方法調用通過AOP的方式進行安全管制,甚至可以對域對象實例(Domain Object Instance)進行訪問控制。
  • 安全保護, 防止偽造身份, Spring Security 會自動攔截站點所有狀態變化的請求(非GET,HEAD,OPTIONS和TRACE的請求),防止跨站請求偽造(CSRF防護),即防止其他網站或是程序POST等請求本站點。
如果項目需要安全控制功能,不用自己去實現一套, 集成Spring Security專業安全框架是首選, 適用後台管理、接口資源管理、微服務統一鑒權等場景。
2. Spring Security設計處理機制

處理流程圖︰






  • 客戶端發起一個請求,進入 Security 過濾器鏈。
  • 當到 LogoutFilter 的時候判斷是否是登出路徑,如果是登出路徑則到 logoutHandler ,如果登出成功則到 logoutSuccessHandler 登出成功處理,如果登出失敗則由 ExceptionTranslationFilter ;如果不是登出路徑則直接進入下一個過濾器。
  • 當到 UsernamePasswordAuthenticationFilter 的時候判斷是否為登錄路徑,如果是,則進入該過濾器進行登錄操作,如果登錄失敗則到 AuthenticationFailureHandler 登錄失敗處理器處理,如果登錄成功則到 AuthenticationSuccessHandler 登錄成功處理器處理,如果不是登錄請求則不進入該過濾器。
  • 當到 FilterSecurityInterceptor 的時候會拿到 uri ,根據 uri 去找對應的鑒權管理器,鑒權管理器做鑒權工作,鑒權成功則到 Controller 層否則到 AccessDeniedHandler 鑒權失敗處理器處理。
  • 投票機制, 三種表決方式, 默認采用一票制(AffirmativeBased
類名
描述
AffirmativeBased
只要有一個投票器允許訪問, 請求立刻允許放行, 不管之前存在拒絕的決定
ConsensusBased
多數票機制(允許或拒絕),多數的一方決定了AccessDecisionManager的結果。平局的投票和空票(全部棄權)的結果是可配置的
UnanimousBased
所有的投票器必須全部是允許的, 否則訪問將被拒絕

3. Spring Boot 與Spring Security 集成配置

Spring Boot 與Spring Security 集成, 包含一般集成用法, 還包括自定義用戶登陸頁面使用, 自定義內存模式驗證, 以及自定義登陸成功與失敗邏輯處理。
1、創建工程spring-boot-security-integrate


啟動類︰

com.mirson.spring.boot.security.integrate.startup.SecurityIntegrateApplication

@SpringBootApplication@ComponentScan(basePackages = {"com.mirson"})public class SecurityIntegrateApplication {    public static void main(String[] args) {        SpringApplication.run(SecurityIntegrateApplication.class, args);    }}2、MAVEN依賴
<dependencies>        <!-- Spring Boot Security 安全依賴組件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-security</artifactId>        </dependency>        <!-- Spring Boot Thymeleaf 模板依賴組件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <!-- Spring Boot Web 依賴組件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!--Spring boot freemarker 自動化配置組件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-freemarker</artifactId>        </dependency>    </dependencies>3、定義一個外部訪問接口
1)創建實體
定義一個用戶實體

com.mirson.spring.boot.security.integrate.po.User

@Datapublic class User {    /**     * ID     */    private Integer id;    /**     * 用戶名稱     */    private String name;    /**     * 年齡     */    private String age;    /**     * 省份     */    private String province;    /**     * 創建時間     */    private Date createDate;}2)提供Web訪問接口
提供一個獲取用戶信息接口

com.mirson.spring.boot.security.integrate.controller.UserController

@RestController@RequestMapping("/user")@Log4j2public class UserController {    @GetMapping("/getUserInfo")    @ResponseBody    public User getUserInfo() {        User user = new User();        user.setId(0);        user.setAge("21");        user.setName("user1");        user.setCreateDate(new Date());        return user;    }}4、工程配置
server:  port: 22618spring:  application:    name: security-integrate  # security 安全配置  security:    user:      name: "admin"      password: "admin"設置默認的用戶名與密碼為admin。
5、功能驗證
1) 請求獲取用戶信息接口
訪問接口︰ http://127.0.0.1:22618/getUserInfo

沒有鑒權的情況下, 會出現登陸界面。



2)輸入用戶信息admin/admin, 再次請求獲取用戶信息接口


正確輸入用戶信息後, 可以正常訪問用戶信息接口。


4. Spring Security 自定義鑒權實現

4.1 自定義登陸頁面處理

Spring Security 內置會有一套登陸頁面, 也可以自定修改, 這里通過freemark模板來實現自定登陸頁面渲染。
application.yml增加配置︰


   # freemarker 模板配置     freemarker:       allow-request-override: false       allow-session-override: false       cache: true       charset: UTF-8       check-template-location: true       content-type: text/html       enabled: true       expose-request-attributes: false       expose-session-attributes: false       expose-spring-macro-helpers: true       prefer-file-system-access: true       suffix: .ftl       template-loader-path: classpath:/templates/   增加freemark模板文件︰
   <!DOCTYPE html>   <html lang="en">     <head>       <meta charset="utf-8">       <meta http-equiv="X-UA-Compatible" content="IE=edge">       <meta name="viewport" content="width=device-width, initial-scale=1">       <meta name="description" content="">       <meta name="author" content="">          <title>自定義系統登陸</title>          <link href="/css/bootstrap.min.css" rel="stylesheet">       <link href="/css/signin.css" rel="stylesheet">     </head>        <body>       <div class="container form-margin-top">         <form class="form-signin" action="/user/doUserLogin" method="post">           <h2 class="form-signin-heading" align="center">自定義系統登陸</h2>           <input type="text" name="username" class="form-control form-margin-top" placeholder="賬號" required autofocus>           <input type="password" name="password" class="form-control" placeholder="密碼" required>           <button class="btn btn-lg btn-primary btn-block" type="submit">sign in</button>         </form>       </div>       <footer>         <p>support by: mirson</p>       </footer>     </body>   </html>   添加CSS靜態資源文件


添加JAVA CONFIG配置︰
com.mirson.spring.boot.security.integrate.config.SpringSecurityConfiguration
   @Configuration   @EnableWebSecurity   public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {       @Override       protected void configure(HttpSecurity http) throws Exception {          http                  .authorizeRequests()                  .antMatchers("/user/userLoginForm",                          "/css/**").permitAll()                  .antMatchers("/user/getUserInfo").authenticated()                   .and()                  .formLogin()                  .loginPage("/user/userLoginForm")    //自定義登錄頁面                               .permitAll()            //允許所有人訪問該路由                  .and()                  .csrf()                  .disable()                //暫時禁用csrc否則無法提交                  .httpBasic();       }   }重啟, 訪問接口︰ http://127.0.0.1:22618/user/getUserInfo
會自動跳轉到自定義的登陸頁面︰


4.2 自定義資源訪問配置

修改com.mirson.spring.boot.security.integrate.config.SpringSecurityConfiguration配置︰
   @Configuration   @EnableWebSecurity   public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {              @Override       protected void configure(HttpSecurity http) throws Exception {          http                  .authorizeRequests()                  .antMatchers("/user/doUserLogin", "/user/userLoginForm",                          "/css/**").permitAll()                  .antMatchers("/user/getUserInfo").authenticated() //hasRole("ADMIN")                  .and()                  .formLogin()                  .loginPage("/user/userLoginForm")    //自定義登錄頁面                  .loginProcessingUrl("/user/doUserLogin") // 自定義登陸處理地址                  .permitAll()            //允許所有人訪問該路由                  .and()                  .csrf()                  .disable()                //暫時禁用csrc否則無法提交                  .httpBasic();       }          }   通過Spring Security 可以控制, 哪些資源需要受權限保護, 哪些可以開放訪問。

  • 開放訪問
/user/userLoginForm 用戶登陸頁面

/user/doUserLogin 登陸處理地址

/css/** 靜態資源文件


  • 權限保護
/user/getUserInfo 獲取用戶信息接口

可以指定Role角色權限, 不指定, 只要登陸即擁有訪問權限。

loginPage指定/user/userLoginForm為自定義登陸頁面;
loginProcessingUrl為登陸請求處理接口地址,可以不用對其做具體實現,Spring Security 會做默認處理。
4.3 自定義內存模式鑒權

1、創建鑒權用戶對象︰

com.mirson.spring.boot.security.integrate.po.OAuthUser
@Datapublic class OAuthUser extends User {    public OAuthUser(String account, String password){        super(account, password, true, true, true, true, Collections.EMPTY_SET);    }}繼承的是Spring Security 的User對象, 將賬號和密碼信息, 傳遞至父類構造方法。
2、修改SpringSecurityConfiguration配置
增加︰

@Configuration@EnableWebSecuritypublic class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {        /**     * 用戶認證服務     * */    @Bean    @Override    protected UserDetailsService userDetailsService() {        //創建基于內存用戶管理對象        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();        //自定義權限        Collection<GrantedAuthority> adminAuth = new ArrayList<>();        adminAuth.add(new SimpleGrantedAuthority("ADMIN"));        //自定義用戶        OAuthUser oAuthUser = new OAuthUser("admin", "admin123");        manager.createUser(oAuthUser);        return manager;    }        /**     * 配置密碼編碼器, 不需加密     * @return     */    @Bean    public static NoOpPasswordEncoder passwordEncoder() {        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();    }        ...}采用內存模式管理用戶對象InMemoryUserDetailsManager, 自定義認證用戶名和密碼, 分別為admin,admin123。 需要配置密碼編碼器, 可以支持自定義密碼加密方式, 這里不需加密, 配置NoOpPasswordEncoder。
4.4 自定義登陸成功處理器

Spring Security 提供了接口, 登陸成功, 可以通過處理器實現自定義邏輯。 新建com.mirson.spring.boot.security.integrate.handler.SecuritySuccessHandler
@Component@Log4j2public class SecuritySuccessHandler extends SimpleUrlAuthenticationSuccessHandler {    @Autowired    private ObjectMapper objectMapper;    /**     * 認證成功處理     * @param request     * @param response     * @param authentication     * @throws IOException     * @throws ServletException     */    @Override    public void onAuthenticationSuccess(HttpServletRequest request,                                        HttpServletResponse response, Authentication authentication) throws IOException, ServletException {        log.info("Process in SecuritySuccessHandler ==> login success.");        response.setContentType("application/json;charset=UTF-8");        response.getWriter().write(objectMapper.writeValueAsString(authentication));    }}這里通過自定義登陸成功處理器, 將登陸成功的信息返回客戶端。
將處理器加入到自定義配置SpringSecurityConfiguration中︰
        @Override    protected void configure(HttpSecurity http) throws Exception {       http               .authorizeRequests()               .antMatchers("/user/doUserLogin", "/user/userLoginForm",                       "/css/**").permitAll()               .antMatchers("/user/getUserInfo").authenticated() //hasRole("ADMIN")               .and()               .formLogin()               .loginPage("/user/userLoginForm")    //自定義登錄頁面               .loginProcessingUrl("/user/doUserLogin") // 自定義登陸處理地址               .successHandler(securitySuccessHandler)  // 自定義登陸成功處理器               .permitAll()            //允許所有人訪問該路由               .and()               .csrf()               .disable()                //暫時禁用csrc否則無法提交               .httpBasic();    }4.5 自定義登陸失敗處理器

如果登陸失敗, 也可以通過處理器實現自定義邏輯。 新建com.mirson.spring.boot.security.integrate.handler.SecurityFailureHandler
@Component@Log4j2public class SecurityFailureHandler extends SimpleUrlAuthenticationFailureHandler {    @Autowired    private ObjectMapper objectMapper;    @Override    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,                                        AuthenticationException exception) throws IOException, ServletException {        log.info("Process in SecurityFailureHandler ==> login failure.");        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());        response.setContentType("application/json;charset=UTF-8");        response.getWriter().write(objectMapper.writeValueAsString(exception.getMessage()));    }}將登陸失敗的錯誤信息, 返回給客戶端。
修改自定義配置SpringSecurityConfiguration︰
@Override    protected void configure(HttpSecurity http) throws Exception {       http               .authorizeRequests()               .antMatchers("/user/doUserLogin", "/user/userLoginForm",                       "/css/**").permitAll()               .antMatchers("/user/getUserInfo").authenticated() //hasRole("ADMIN")               .and()               .formLogin()               .loginPage("/user/userLoginForm")    //自定義登錄頁面               .loginProcessingUrl("/user/doUserLogin") // 自定義登陸處理地址               .successHandler(securitySuccessHandler)  // 自定義登陸成功處理器               .failureHandler(securityFailureHandler)  // 自定義登陸失敗處理器               .permitAll()            //允許所有人訪問該路由               .and()               .csrf()               .disable()                //暫時禁用csrc否則無法提交               .httpBasic();    }4.6 自定義鑒權功能驗證

1、驗證內存模式鑒權

內存模式我們設置的用戶名和密碼為admin/admin123

默認配置文件是admin/admin


輸入admin/admin123, 成功登陸, 內存模式已生效。
2、登陸成功處理器驗證
重啟服務, 訪問獲取用戶信息接口, http://127.0.0.1:22618/user/getUserInfo

默認是會跳轉到登陸頁面, 如果沒配置登陸成功處理器, 登陸成功後, 會進入上一次訪問頁面



可以看到, 登陸成功後, 並沒有跳轉到上一次訪問的用戶信息接口, 而是返回了登陸成功處理器的結果。
3、登陸失敗處理器驗證
同樣, 問獲取用戶信息接口, http://127.0.0.1:22618/user/getUserInfo, 會自動跳轉到登陸頁面。


采用錯誤的用戶密碼, 返回了登陸失敗處理器的結果。
5. 總結

Spring Security 提供了鑒權與授權的功能支持, 這里做了詳細講解, 如何使用與配置, 並講解了自定義鑒權處理功能, 實際業務當中,並非一層不變, 會做不同配置修改,比如自定義資源訪問配置, 不同項目有不同的要求, 掌握這些自定義配置, 基本可以覆蓋主要的業務場景, 針對更復雜的鑒權, 可以采用oauth2做鑒權處理, 在後續教程中會做講解。
教程源碼下載地址︰ https://download.csdn.net/download/hxx688/86400104

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|小黑屋|黑莲技术资源论坛 ( 闽ICP备18016623号-7 )|网站地图

GMT+8, 2022-10-7 20:22 , Processed in 0.446522 second(s), 26 queries .

Powered by BBS.HL1.NET X3.4 © 2020-2022

本站IT社区(bbs.hl1.net)所有的资源教程均来自网友分享及互联网收集

快速回复 返回顶部 返回列表