最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot整合SpringSecurity的完整案例詳解

 更新時(shí)間:2024年01月22日 09:51:23   作者:kangkang-  
Spring Security是基于Spring生態(tài)圈的,用于提供安全訪問控制解決方案的框架,Spring Security登錄認(rèn)證主要涉及兩個(gè)重要的接口 UserDetailService和UserDetails接口,本文對(duì)Springboot整合SpringSecurity過程給大家介紹的非常詳細(xì),需要的朋友參考下吧

一.Spring Security介紹

Spring Security是基于Spring生態(tài)圈的,用于提供安全訪問控制解決方案的框架。Spring Security的安 全管理有兩個(gè)重要概念,分別是Authentication(認(rèn)證)和Authorization(授權(quán))。 為了方便Spring Boot項(xiàng)目的安全管理,Spring Boot對(duì)Spring Security安全框架進(jìn)行了整合支持,并提 供了通用的自動(dòng)化配置,從而實(shí)現(xiàn)了Spring Security安全框架中包含的多數(shù)安全管理功能。

Spring Security登錄認(rèn)證主要涉及兩個(gè)重要的接口 UserDetailService和UserDetails接口。

UserDetailService接口主要定義了一個(gè)方法 loadUserByUsername(String username)用于完成用戶信息的查 詢,其中username就是登錄時(shí)的登錄名稱,登錄認(rèn)證時(shí),需要自定義一個(gè)實(shí)現(xiàn)類實(shí)現(xiàn)UserDetailService接 口,完成數(shù)據(jù)庫查詢,該接口返回UserDetail。

UserDetail主要用于封裝認(rèn)證成功時(shí)的用戶信息,即UserDetailService返回的用戶信息,可以用Spring

自己的User對(duì)象,但是最好是實(shí)現(xiàn)UserDetail接口,自定義用戶對(duì)象。

二.Spring Security認(rèn)證步驟

1. 自定UserDetails類:當(dāng)實(shí)體對(duì)象字段不滿足時(shí)需要自定義UserDetails,一般都要自定義

UserDetails。

2. 自定義UserDetailsService類,主要用于從數(shù)據(jù)庫查詢用戶信息。

3. 創(chuàng)建登錄認(rèn)證成功處理器,認(rèn)證成功后需要返回JSON數(shù)據(jù),菜單權(quán)限等。

4. 創(chuàng)建登錄認(rèn)證失敗處理器,認(rèn)證失敗需要返回JSON數(shù)據(jù),給前端判斷。

5. 創(chuàng)建匿名用戶訪問無權(quán)限資源時(shí)處理器,匿名用戶訪問時(shí),需要提示JSON。

6. 創(chuàng)建認(rèn)證過的用戶訪問無權(quán)限資源時(shí)的處理器,無權(quán)限訪問時(shí),需要提示JSON。

7. 配置Spring Security配置類,把上面自定義的處理器交給Spring Security。

三.Spring Security認(rèn)證實(shí)現(xiàn)

3.1添加Spring Security依賴

在pom.xml文件中添加Spring Security核心依賴,代碼如下所

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

3.2自定義UserDetails

   當(dāng)實(shí)體對(duì)象字段不滿足時(shí)Spring Security認(rèn)證時(shí),需要自定義UserDetails。

   1. 將User類實(shí)現(xiàn)UserDetails接口

   2. 將原有的isAccountNonExpired、isAccountNonLocked、isCredentialsNonExpired和isEnabled屬性修 改成boolean類型,同時(shí)添加authorities屬性。

@Data
@TableName("sys_user")
public class User implements Serializable, UserDetails {
    //省略原有的屬性......
    /**
     * 帳戶是否過期(1 未過期,0已過期)
     */
    private boolean isAccountNonExpired = true;
    /**
     * 帳戶是否被鎖定(1 未過期,0已過期)
     */
    private boolean isAccountNonLocked = true;
    /**
     * 密碼是否過期(1 未過期,0已過期)
     */
    private boolean isCredentialsNonExpired = true;
    /**
     * 帳戶是否可用(1 可用,0 刪除用戶)
     */
    private boolean isEnabled = true;
    /**
     * 權(quán)限列表
     */
    @TableField(exist = false)
    Collection<? extends GrantedAuthority> authorities;

3.3.編寫Service接口

public interface UserService extends IService<User> {
    /**
     * 根據(jù)用戶名查詢用戶信息
     * @param userName
     * @return
     */
    User findUserByUserName(String userName);
}

3.4.編寫ServiceImpl

package com.manong.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.manong.entity.User;
import com.manong.dao.UserMapper;
import com.manong.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
 * <p>
 *  服務(wù)實(shí)現(xiàn)類
 * </p>
 *
 * @author lemon
 * @since 2022-12-06
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Override
    public User findUserByUserName(String username) {
        //創(chuàng)建條件構(gòu)造器對(duì)象
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("username",username);
        //執(zhí)行查詢
        return baseMapper.selectOne(queryWrapper);
    }
}

3.5. 自定義UserDetailsService類

package com.manong.config.security.service;
import com.manong.entity.Permission;
import com.manong.entity.User;
import com.manong.service.PermissionService;
import com.manong.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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 javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/*
* 用戶認(rèn)證處理器類
* */
@Component
public class CustomerUserDetailService implements UserDetailsService {
    @Resource
    private UserService userService;
    @Resource
    private PermissionService permissionService;
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        //根據(jù)對(duì)象查找用戶信息
        User user = userService.findUserByUserName(username);
        //判斷對(duì)象是否為空
        if(user==null){
            throw new UsernameNotFoundException("用戶的賬號(hào)密碼錯(cuò)誤");
        }
        //查詢當(dāng)前登錄用戶擁有權(quán)限列表
        List<Permission> permissionList = permissionService.findPermissionListByUserId(user.getId());
        //獲取對(duì)應(yīng)的權(quán)限編碼
        List<String> codeList = permissionList.stream()
                .filter(Objects::nonNull)
                .map(item -> item.getCode())
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        //將權(quán)限編碼轉(zhuǎn)換成數(shù)據(jù)
        String [] strings=codeList.toArray(new String[codeList.size()]);
        //設(shè)置權(quán)限列表
        List<GrantedAuthority> authorityList = AuthorityUtils.createAuthorityList(strings);
        //將權(quán)限列表設(shè)置給User
        user.setAuthorities(authorityList);
        //設(shè)置該用戶擁有的菜單
        user.setPermissionList(permissionList);
        //查詢成功
        return user;
    }
}

四.通常情況下,我們需要自定義四個(gè)類來獲取處理類 包括成功,失敗,匿名用戶,登錄了但沒有權(quán)限的用戶

4.1.成功

package com.manong.config.security.handler;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.manong.entity.User;
import com.manong.utils.JwtUtils;
import com.manong.utils.LoginResult;
import com.manong.utils.ResultCode;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import sun.net.www.protocol.http.AuthenticationHeader;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import com.alibaba.fastjson.JSON;
/*
 * 登錄認(rèn)證成功處理器類
 * */
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Resource
    private JwtUtils jwtUtils;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //設(shè)置相應(yīng)編碼格式
        response.setContentType("application/json;charset-utf-8");
        //獲取當(dāng)前登錄用戶的信息
        User user = (User) authentication.getPrincipal();
        //創(chuàng)建token對(duì)象
        String token = jwtUtils.generateToken(user);
        //設(shè)置token的秘鑰和過期時(shí)間
        long expireTime = Jwts.parser()
                .setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(token.replace("jwt_", ""))
                .getBody().getExpiration().getTime();//設(shè)置過期時(shí)間
        //創(chuàng)建LOgin登錄對(duì)象
        LoginResult loginResult=new LoginResult(user.getId(), ResultCode.SUCCESS,token,expireTime);
        //將對(duì)象轉(zhuǎn)換成json格式
        //消除循環(huán)引用
        String result = JSON.toJSONString(loginResult, SerializerFeature.DisableCircularReferenceDetect);
        //獲取輸出流
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

4.2 失敗

package com.manong.config.security.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.api.R;
import com.manong.entity.User;
import com.manong.utils.Result;
import com.manong.utils.ResultCode;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        //設(shè)置相應(yīng)編碼格式
        response.setContentType("application/json;charset-utf-8");
        //獲取輸出流
        ServletOutputStream outputStream = response.getOutputStream();
        //定義變量,保存異常信息
        String message=null;
        //判斷異常類型
        if(exception instanceof AccountExpiredException){
            message="賬戶過期失敗";
        }
        else if(exception instanceof BadCredentialsException){
            message="用戶名的賬號(hào)密碼錯(cuò)誤,登錄失敗";
        }
        else if(exception instanceof CredentialsExpiredException){
            message="密碼過期,登錄失敗";
        }
        else if(exception instanceof DisabledException){
            message="賬號(hào)過期,登錄失敗";
        }
        else if(exception instanceof LockedException){
            message="賬號(hào)被上鎖,登錄失敗";
        }
        else if(exception instanceof InternalAuthenticationServiceException){
            message="用戶不存在";
        }
        else {
            message="登錄失敗";
        }
        //將結(jié)果轉(zhuǎn)換為Json格式
        String result = JSON.toJSONString(Result.error().code(ResultCode.ERROR).message(message));
        //將結(jié)果保存到輸出中
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

 4.3 匿名無用戶

package com.manong.config.security.handler;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.manong.entity.User;
import com.manong.utils.Result;
import com.manong.utils.ResultCode;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import sun.net.www.protocol.http.AuthenticationHeader;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import com.alibaba.fastjson.JSON;
/*
 * 匿名訪問無權(quán)限資源處理器
 * */
@Component
public class AnonymousAuthenticationHandler implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setContentType("application/json;charset-utf-8");
        //獲取輸出流
        ServletOutputStream outputStream = response.getOutputStream();
        //將對(duì)象轉(zhuǎn)換成json格式
        //消除循環(huán)引用
        String result = JSON.toJSONString(Result.error().code(ResultCode.NO_AUTH).message("匿名用戶無權(quán)限訪問"), SerializerFeature.DisableCircularReferenceDetect);
        //獲取輸出流
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

 4.4 登錄了但是沒有權(quán)限的用戶

package com.manong.config.security.handler;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.manong.entity.User;
import com.manong.utils.Result;
import com.manong.utils.ResultCode;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import sun.net.www.protocol.http.AuthenticationHeader;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import com.alibaba.fastjson.JSON;
/*
 * 認(rèn)證用戶訪問無權(quán)限資源處理器
 * */
@Component
public class CustomerAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setContentType("application/json;charset-utf-8");
        ServletOutputStream outputStream = response.getOutputStream();
        //將對(duì)象轉(zhuǎn)換成json格式
        //消除循環(huán)引用
        String result = JSON.toJSONString(Result.error().code(ResultCode.NO_AUTH).message("用戶無權(quán)限訪問,請(qǐng)聯(lián)系教務(wù)處"), SerializerFeature.DisableCircularReferenceDetect);
        //獲取輸出流
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}

五.編寫SpringSecurity配置類,把上面的四個(gè)類進(jìn)行合并

package com.manong.config.security.service;
import com.manong.config.security.handler.AnonymousAuthenticationHandler;
import com.manong.config.security.handler.CustomerAccessDeniedHandler;
import com.manong.config.security.handler.LoginFailureHandler;
import com.manong.config.security.handler.LoginSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private LoginSuccessHandler loginSuccessHandler;
    @Resource
    private LoginFailureHandler loginFailureHandler;
    @Resource
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;
    @Resource
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;
    @Resource
    private CustomerUserDetailService customerUserDetailService;
    //注入加密類
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    //處理登錄認(rèn)證
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //登錄過程處理
        http.formLogin()    //表單登錄
                .loginProcessingUrl("/api/user/login") //登錄請(qǐng)求url地址
                .successHandler(loginSuccessHandler)   //認(rèn)證成功
                .failureHandler(loginFailureHandler)   //認(rèn)證失敗
                .and()
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) //不創(chuàng)建Session
                .and().authorizeRequests() //設(shè)置需要攔截的請(qǐng)求
                .antMatchers("/api/user/login").permitAll()//登錄放行
                .anyRequest().authenticated()  //其他請(qǐng)求一律攔截
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(anonymousAuthenticationHandler)  //匿名無權(quán)限類
                .accessDeniedHandler(customerAccessDeniedHandler)       //認(rèn)證用戶無權(quán)限
                .and()
                .cors();//支持跨域
    }
    //認(rèn)證配置處理器
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerUserDetailService)
                .passwordEncoder(this.passwordEncoder());//密碼加密
    }
}

到此這篇關(guān)于Springboot整合SpringSecurity的文章就介紹到這了,更多相關(guān)Springboot整合SpringSecurity內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot靜態(tài)資源(static)無法訪問問題404及解決過程

    springboot靜態(tài)資源(static)無法訪問問題404及解決過程

    文章瀏覽閱讀7.8k次。本文介紹了SpringBoot項(xiàng)目中遇到的靜態(tài)資源無法訪問的問題及解決辦法。主要從攔截器配置、靜態(tài)資源映射配置和pom.xml文件配置三個(gè)方面進(jìn)行詳細(xì)說明。
    2026-05-05
  • maven依賴關(guān)系中的<scope>provided</scope>使用詳解

    maven依賴關(guān)系中的<scope>provided</scope>使用詳解

    這篇文章主要介紹了maven依賴關(guān)系中的<scope>provided</scope>使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java中InputSteam怎么轉(zhuǎn)String

    Java中InputSteam怎么轉(zhuǎn)String

    面了一位實(shí)習(xí)生,叫他給我說一下怎么把InputStream轉(zhuǎn)換為String,這種常規(guī)的操作,他竟然都沒有用過我準(zhǔn)備結(jié)合工作經(jīng)驗(yàn),整理匯集出了InputStream 到String 轉(zhuǎn)換的十八般武藝,助大家闖蕩 Java 江湖一臂之力,需要的朋友可以參考下
    2021-06-06
  • 2020年IntelliJ IDEA最新最詳細(xì)配置圖文教程詳解

    2020年IntelliJ IDEA最新最詳細(xì)配置圖文教程詳解

    這篇文章主要介紹了2020年IntelliJ IDEA最新最詳細(xì)配置圖文教程詳解,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 解決Spring boot 嵌入的tomcat不啟動(dòng)問題

    解決Spring boot 嵌入的tomcat不啟動(dòng)問題

    這篇文章主要介紹了解決Spring boot 嵌入的tomcat不啟動(dòng)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java多種方式實(shí)現(xiàn)Excel轉(zhuǎn)Pdf的保姆級(jí)教程

    Java多種方式實(shí)現(xiàn)Excel轉(zhuǎn)Pdf的保姆級(jí)教程

    在企業(yè)級(jí)系統(tǒng)使用或日常使用中,我們經(jīng)常使用excel表格數(shù)據(jù)進(jìn)行瀏覽數(shù)據(jù),但有時(shí)候我們會(huì)想要將excel轉(zhuǎn)換成pdf進(jìn)行預(yù)覽使用,本篇博文以java進(jìn)行編寫多種實(shí)現(xiàn)方式實(shí)現(xiàn)多sheet頁excel轉(zhuǎn)換一個(gè)pdf的需求,需要的朋友可以參考下
    2025-08-08
  • java使用GeoTools讀取shp文件并畫圖的操作代碼

    java使用GeoTools讀取shp文件并畫圖的操作代碼

    GeoTools是ArcGis地圖與java對(duì)象的橋梁,今天通過本文給大家分享java使用GeoTools讀取shp文件并畫圖,文章通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-07-07
  • jackson json序列化實(shí)現(xiàn)首字母大寫,第二個(gè)字母需小寫

    jackson json序列化實(shí)現(xiàn)首字母大寫,第二個(gè)字母需小寫

    這篇文章主要介紹了jackson json序列化實(shí)現(xiàn)首字母大寫,第二個(gè)字母需小寫方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • java中Map和List初始化的N種方法總結(jié)

    java中Map和List初始化的N種方法總結(jié)

    這篇文章主要介紹了java中Map和List初始化的N種方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • IDEA教程創(chuàng)建SpringBoot前后端分離項(xiàng)目示例圖解

    IDEA教程創(chuàng)建SpringBoot前后端分離項(xiàng)目示例圖解

    在使用spring、mybatis等框架時(shí),配置文件很復(fù)雜,有時(shí)復(fù)雜的讓人想放棄Java,使用C#。springboot出現(xiàn)這一切問題就都不是問題
    2021-10-10

最新評(píng)論

汤阴县| 万全县| 晋宁县| 佳木斯市| 永定县| 郧西县| 石首市| 金沙县| 荆州市| 大竹县| 梁山县| 马龙县| 峨边| 报价| 文水县| 西华县| 台前县| 崇州市| 长乐市| 峨边| 山东省| 台东县| 神池县| 福海县| 锡林浩特市| 西林县| 洛宁县| 双江| 万荣县| 广州市| 历史| 镇平县| 抚远县| 象州县| 图木舒克市| 青神县| 巩义市| 晴隆县| 富平县| 天全县| 建湖县|