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

SpringSecurity授權(quán)機(jī)制的實(shí)現(xiàn)(AccessDecisionManager與投票決策)

 更新時(shí)間:2025年04月13日 10:16:21   作者:程序媛學(xué)姐  
本文主要介紹了SpringSecurity授權(quán)機(jī)制的實(shí)現(xiàn),其核心是AccessDecisionManager和投票系統(tǒng),下面就來(lái)介紹一下,感興趣的可以了解一下

引言

在企業(yè)級(jí)應(yīng)用開(kāi)發(fā)中,安全控制不僅包括認(rèn)證(Authentication)——確認(rèn)用戶身份,還包括授權(quán)(Authorization)——確定用戶是否有權(quán)執(zhí)行特定操作。Spring Security提供了一套精心設(shè)計(jì)的授權(quán)機(jī)制,其核心是AccessDecisionManager和投票系統(tǒng)。與簡(jiǎn)單的角色檢查相比,這種機(jī)制提供了更細(xì)粒度、更靈活的訪問(wèn)控制能力。本文將深入探討Spring Security授權(quán)框架的內(nèi)部工作原理,重點(diǎn)分析AccessDecisionManager如何通過(guò)投票機(jī)制做出授權(quán)決策,以及如何根據(jù)業(yè)務(wù)需求進(jìn)行定制化配置。通過(guò)這些知識(shí),開(kāi)發(fā)者可以構(gòu)建既安全又靈活的訪問(wèn)控制系統(tǒng)。

一、Spring Security授權(quán)架構(gòu)

Spring Security的授權(quán)架構(gòu)采用了責(zé)任鏈和投票模式相結(jié)合的設(shè)計(jì),使授權(quán)決策過(guò)程模塊化且可擴(kuò)展。授權(quán)過(guò)程始于SecurityFilterChain中的FilterSecurityInterceptor,它攔截受保護(hù)資源的請(qǐng)求,收集安全元數(shù)據(jù)(如所需權(quán)限),然后委托給AccessDecisionManager進(jìn)行授權(quán)判斷。AccessDecisionManager通過(guò)組合多個(gè)AccessDecisionVoter實(shí)現(xiàn)復(fù)雜的授權(quán)策略,每個(gè)投票者根據(jù)自己的邏輯對(duì)授權(quán)請(qǐng)求投贊成、反對(duì)或棄權(quán)票。這種分層設(shè)計(jì)使得授權(quán)邏輯與業(yè)務(wù)代碼完全分離,便于維護(hù)和擴(kuò)展。

// FilterSecurityInterceptor 關(guān)鍵部分
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor {
    
    private final FilterInvocationSecurityMetadataSource securityMetadataSource;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        // 封裝HTTP請(qǐng)求
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        
        // 進(jìn)行安全攔截
        invoke(fi);
    }
    
    public void invoke(FilterInvocation fi) throws IOException, ServletException {
        // 檢查安全攔截器是否應(yīng)該被應(yīng)用
        if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)) {
            // 安全攔截器已應(yīng)用,繼續(xù)執(zhí)行過(guò)濾器鏈
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            return;
        }
        
        // 標(biāo)記攔截器已應(yīng)用
        fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
        
        // 執(zhí)行安全攔截
        InterceptorStatusToken token = super.beforeInvocation(fi);
        
        try {
            // 繼續(xù)執(zhí)行過(guò)濾器鏈
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            // 清理安全上下文
            super.finallyInvocation(token);
        }
        
        // 執(zhí)行后處理
        super.afterInvocation(token, null);
    }
    
    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;
    }
    
    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }
}

二、AccessDecisionManager接口設(shè)計(jì)

AccessDecisionManager是Spring Security授權(quán)體系的核心接口,負(fù)責(zé)協(xié)調(diào)多個(gè)AccessDecisionVoter并做出最終授權(quán)決策。它定義了三個(gè)關(guān)鍵方法:decide()執(zhí)行授權(quán)判斷,supports(ConfigAttribute)檢查是否支持特定配置屬性,supports(Class)檢查是否支持特定安全對(duì)象類(lèi)型。通過(guò)這些方法,AccessDecisionManager可以靈活處理不同類(lèi)型的授權(quán)請(qǐng)求,如Web請(qǐng)求、方法調(diào)用或特定領(lǐng)域?qū)ο蟮脑L問(wèn)。Spring Security提供了三種內(nèi)置實(shí)現(xiàn):AffirmativeBased(只要有一票贊成即通過(guò))、ConsensusBased(多數(shù)票決定)和UnanimousBased(要求全票通過(guò))。

// AccessDecisionManager接口定義
public interface AccessDecisionManager {
    /**
     * 對(duì)給定的安全對(duì)象做出訪問(wèn)控制決策
     * @param authentication 當(dāng)前用戶的認(rèn)證信息
     * @param object 要訪問(wèn)的安全對(duì)象
     * @param configAttributes 安全對(duì)象的安全配置屬性
     * @throws AccessDeniedException 如果拒絕訪問(wèn)
     * @throws InsufficientAuthenticationException 如果認(rèn)證不足
     */
    void decide(Authentication authentication, Object object, 
            Collection<ConfigAttribute> configAttributes) 
            throws AccessDeniedException, InsufficientAuthenticationException;
    
    /**
     * 檢查此AccessDecisionManager是否支持指定的ConfigAttribute
     * @param attribute 要檢查的配置屬性
     * @return 如果支持該屬性返回true
     */
    boolean supports(ConfigAttribute attribute);
    
    /**
     * 檢查此AccessDecisionManager是否支持指定的安全對(duì)象類(lèi)型
     * @param clazz 安全對(duì)象的類(lèi)型
     * @return 如果支持該類(lèi)型返回true
     */
    boolean supports(Class<?> clazz);
}

三、投票決策實(shí)現(xiàn)

Spring Security提供了三種不同的AccessDecisionManager實(shí)現(xiàn),每種實(shí)現(xiàn)代表不同的投票策略。AffirmativeBased采用"一票通過(guò)"策略,只要有一個(gè)投票者投贊成票就允許訪問(wèn),這是最寬松的策略。ConsensusBased基于"多數(shù)票"原則,根據(jù)贊成票與反對(duì)票的比較結(jié)果做出決策。UnanimousBased要求所有投票者都投贊成票(或棄權(quán))才允許訪問(wèn),是最嚴(yán)格的策略。這三種實(shí)現(xiàn)覆蓋了從寬松到嚴(yán)格的不同安全需求,開(kāi)發(fā)者可以根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的策略。

// AffirmativeBased實(shí)現(xiàn)關(guān)鍵代碼
public class AffirmativeBased extends AbstractAccessDecisionManager {
    
    public AffirmativeBased(List<AccessDecisionVoter<?>> decisionVoters) {
        super(decisionVoters);
    }
    
    @Override
    public void decide(Authentication authentication, Object object, 
            Collection<ConfigAttribute> attributes) 
            throws AccessDeniedException {
        int deny = 0;
        
        // 遍歷所有投票者
        for (AccessDecisionVoter voter : getDecisionVoters()) {
            // 獲取投票結(jié)果
            int result = voter.vote(authentication, object, attributes);
            
            switch (result) {
            case AccessDecisionVoter.ACCESS_GRANTED: // 投票通過(guò)
                return; // 立即返回允許訪問(wèn)
            case AccessDecisionVoter.ACCESS_DENIED: // 投票拒絕
                deny++; // 計(jì)數(shù)拒絕票
                break;
            default: // 棄權(quán)
                break;
            }
        }
        
        // 如果有拒絕票且沒(méi)有通過(guò)票,則拒絕訪問(wèn)
        if (deny > 0) {
            throw new AccessDeniedException("訪問(wèn)被拒絕,安全投票失敗");
        }
        
        // 所有投票者棄權(quán),根據(jù)配置決定(默認(rèn)允許)
        if (getAllowIfAllAbstainDecisions()) {
            return;
        }
        
        // 默認(rèn)拒絕訪問(wèn)
        throw new AccessDeniedException("訪問(wèn)被拒絕,沒(méi)有投票者同意");
    }
}

四、AccessDecisionVoter機(jī)制

AccessDecisionVoter是Spring Security授權(quán)機(jī)制中的投票者角色,負(fù)責(zé)對(duì)特定授權(quán)請(qǐng)求投票。每個(gè)投票者實(shí)現(xiàn)vote()方法,返回ACCESS_GRANTED(贊成)、ACCESS_DENIED(反對(duì))或ACCESS_ABSTAIN(棄權(quán))。常用的投票者包括:RoleVoter(基于角色投票)、AuthenticatedVoter(基于認(rèn)證狀態(tài)投票)和WebExpressionVoter(基于SpEL表達(dá)式投票)。投票者的靈活性在于它可以基于任何條件做出決策,不僅限于用戶角色,還可以考慮時(shí)間、位置、資源屬性等因素。

// AccessDecisionVoter接口
public interface AccessDecisionVoter<S> {
    /**
     * 贊成訪問(wèn)的常量
     */
    int ACCESS_GRANTED = 1;
    
    /**
     * 拒絕訪問(wèn)的常量
     */
    int ACCESS_DENIED = -1;
    
    /**
     * 棄權(quán)的常量
     */
    int ACCESS_ABSTAIN = 0;
    
    /**
     * 對(duì)訪問(wèn)請(qǐng)求進(jìn)行投票
     * @param authentication 當(dāng)前用戶的認(rèn)證信息
     * @param object 要訪問(wèn)的安全對(duì)象
     * @param attributes 安全對(duì)象的配置屬性
     * @return 投票結(jié)果:ACCESS_GRANTED、ACCESS_DENIED或ACCESS_ABSTAIN
     */
    int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
    
    /**
     * 檢查此投票者是否支持指定的配置屬性
     * @param attribute 要檢查的配置屬性
     * @return 如果支持該屬性返回true
     */
    boolean supports(ConfigAttribute attribute);
    
    /**
     * 檢查此投票者是否支持指定的安全對(duì)象類(lèi)型
     * @param clazz 安全對(duì)象的類(lèi)型
     * @return 如果支持該類(lèi)型返回true
     */
    boolean supports(Class<?> clazz);
}

// RoleVoter實(shí)現(xiàn)
public class RoleVoter implements AccessDecisionVoter<Object> {
    
    private String rolePrefix = "ROLE_";
    
    public int vote(Authentication authentication, Object object, 
            Collection<ConfigAttribute> attributes) {
        // 如果沒(méi)有屬性,棄權(quán)
        if (attributes.isEmpty()) {
            return ACCESS_ABSTAIN;
        }
        
        // 獲取用戶權(quán)限
        Collection<? extends GrantedAuthority> authorities = 
                authentication.getAuthorities();
        
        // 檢查每個(gè)配置屬性
        for (ConfigAttribute attribute : attributes) {
            if (this.supports(attribute)) {
                // 屬性值作為需要的角色
                String role = attribute.getAttribute();
                
                // 檢查用戶是否擁有該角色
                for (GrantedAuthority authority : authorities) {
                    if (role.equals(authority.getAuthority())) {
                        return ACCESS_GRANTED; // 用戶有所需角色,允許訪問(wèn)
                    }
                }
                
                // 走到這里說(shuō)明用戶沒(méi)有所需角色,返回拒絕
                return ACCESS_DENIED;
            }
        }
        
        // 沒(méi)有可支持的屬性,棄權(quán)
        return ACCESS_ABSTAIN;
    }
    
    @Override
    public boolean supports(ConfigAttribute attribute) {
        // 檢查屬性是否以角色前綴開(kāi)頭
        return (attribute.getAttribute() != null) && 
                attribute.getAttribute().startsWith(rolePrefix);
    }
    
    @Override
    public boolean supports(Class<?> clazz) {
        return true; // 支持所有類(lèi)型的安全對(duì)象
    }
}

五、自定義訪問(wèn)控制規(guī)則

Spring Security的授權(quán)機(jī)制最大的優(yōu)勢(shì)在于其可擴(kuò)展性,開(kāi)發(fā)者可以輕松實(shí)現(xiàn)自定義的訪問(wèn)控制規(guī)則。通過(guò)創(chuàng)建自定義的AccessDecisionVoter,可以基于業(yè)務(wù)特定邏輯進(jìn)行授權(quán)決策,如限制特定時(shí)間段的訪問(wèn)、根據(jù)用戶屬性控制權(quán)限或?qū)崿F(xiàn)數(shù)據(jù)行級(jí)安全。自定義投票者只需實(shí)現(xiàn)AccessDecisionVoter接口的三個(gè)方法,然后將其添加到AccessDecisionManager的投票者列表中即可。這種方式使復(fù)雜的授權(quán)需求變得易于實(shí)現(xiàn)且可維護(hù)。

// 自定義的工作時(shí)間投票者,只允許在工作時(shí)間訪問(wèn)
public class BusinessHoursVoter implements AccessDecisionVoter<Object> {
    
    private final int startHour = 9;  // 工作開(kāi)始時(shí)間
    private final int endHour = 17;   // 工作結(jié)束時(shí)間
    
    @Override
    public int vote(Authentication authentication, Object object, 
            Collection<ConfigAttribute> attributes) {
        // 檢查是否有工作時(shí)間限制的屬性
        boolean businessHoursRequired = attributes.stream()
                .anyMatch(a -> "BUSINESS_HOURS_ONLY".equals(a.getAttribute()));
        
        // 如果沒(méi)有時(shí)間限制,棄權(quán)
        if (!businessHoursRequired) {
            return ACCESS_ABSTAIN;
        }
        
        // 獲取當(dāng)前時(shí)間
        LocalTime now = LocalTime.now();
        int currentHour = now.getHour();
        
        // 檢查是否在工作時(shí)間內(nèi)
        if (currentHour >= startHour && currentHour < endHour) {
            return ACCESS_GRANTED;
        } else {
            return ACCESS_DENIED;
        }
    }
    
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return attribute != null && "BUSINESS_HOURS_ONLY".equals(attribute.getAttribute());
    }
    
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}

// 自定義配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").access("hasRole('ADMIN') and hasAuthority('BUSINESS_HOURS_ONLY')")
                .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/login").permitAll();
        
        // 替換默認(rèn)的AccessDecisionManager
        http.authorizeRequests()
                .accessDecisionManager(accessDecisionManager());
    }
    
    @Bean
    public AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<?>> voters = new ArrayList<>();
        voters.add(new WebExpressionVoter());
        voters.add(new RoleVoter());
        voters.add(new AuthenticatedVoter());
        voters.add(new BusinessHoursVoter());  // 添加自定義投票者
        
        // 使用"一票通過(guò)"策略
        return new AffirmativeBased(voters);
    }
}

六、方法級(jí)安全控制

除了Web請(qǐng)求的授權(quán)控制外,Spring Security還提供了方法級(jí)別的安全控制,使開(kāi)發(fā)者能夠直接在業(yè)務(wù)方法上應(yīng)用授權(quán)規(guī)則。通過(guò)@PreAuthorize、@PostAuthorize等注解,可以使用SpEL表達(dá)式定義復(fù)雜的訪問(wèn)條件。這些注解由MethodSecurityInterceptor處理,它同樣使用AccessDecisionManager進(jìn)行授權(quán)決策。方法級(jí)安全與Web安全共享相同的授權(quán)架構(gòu),但提供了更精細(xì)的控制粒度,特別適合業(yè)務(wù)邏輯層的權(quán)限管理。

// 啟用方法級(jí)安全
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        // 自定義方法級(jí)安全的AccessDecisionManager
        AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();
        
        // 獲取現(xiàn)有的投票者并添加自定義投票者
        List<AccessDecisionVoter<?>> voters = new ArrayList<>(
                accessDecisionManager.getDecisionVoters());
        voters.add(new BusinessHoursVoter());
        
        // 創(chuàng)建新的AccessDecisionManager
        return new AffirmativeBased(voters);
    }
}

// 在服務(wù)類(lèi)中使用方法級(jí)安全
@Service
public class UserService {
    
    @PreAuthorize("hasRole('ADMIN') and hasAuthority('BUSINESS_HOURS_ONLY')")
    public void deleteUser(Long userId) {
        // 刪除用戶的邏輯
    }
    
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public UserDetails viewUserProfile(Long userId) {
        // 查看用戶資料的邏輯
        return userProfile;
    }
    
    @PostAuthorize("returnObject.username == authentication.name or hasRole('ADMIN')")
    public UserDetails loadUserById(Long userId) {
        // 只允許查看自己的詳細(xì)信息或者管理員查看
        return userDetails;
    }
}

總結(jié)

Spring Security的授權(quán)機(jī)制以AccessDecisionManager和投票決策系統(tǒng)為核心,提供了一套靈活而強(qiáng)大的訪問(wèn)控制框架。通過(guò)責(zé)任鏈模式和策略模式的結(jié)合,它實(shí)現(xiàn)了授權(quán)邏輯的模塊化和可擴(kuò)展性。AccessDecisionManager協(xié)調(diào)多個(gè)AccessDecisionVoter,根據(jù)不同的投票策略做出最終授權(quán)決策,支持從寬松到嚴(yán)格的各種安全需求。內(nèi)置的投票者如RoleVoter和WebExpressionVoter滿足了基本授權(quán)場(chǎng)景,而自定義投票者則使復(fù)雜的業(yè)務(wù)規(guī)則得以實(shí)現(xiàn)。方法級(jí)安全控制進(jìn)一步擴(kuò)展了授權(quán)能力,使開(kāi)發(fā)者能夠在業(yè)務(wù)方法層面應(yīng)用精細(xì)的權(quán)限管理。理解并掌握這套授權(quán)機(jī)制,開(kāi)發(fā)者可以構(gòu)建既安全又靈活的企業(yè)級(jí)應(yīng)用,有效平衡安全需求與用戶體驗(yàn)。在安全威脅日益復(fù)雜的今天,Spring Security的授權(quán)框架為開(kāi)發(fā)者提供了應(yīng)對(duì)挑戰(zhàn)的有力工具,使復(fù)雜的授權(quán)邏輯變得清晰可維護(hù),為應(yīng)用系統(tǒng)的安全基礎(chǔ)奠定了堅(jiān)實(shí)基礎(chǔ)。

到此這篇關(guān)于SpringSecurity授權(quán)機(jī)制的實(shí)現(xiàn)(AccessDecisionManager與投票決策)的文章就介紹到這了,更多相關(guān)SpringSecurity授權(quán)機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談Java異常的Exception e中的egetMessage()和toString()方法的區(qū)別

    淺談Java異常的Exception e中的egetMessage()和toString()方法的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談Java異常的Exception e中的egetMessage()和toString()方法的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦

    java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦

    這篇文章主要為大家介紹了java開(kāi)源好用的簡(jiǎn)繁轉(zhuǎn)換類(lèi)庫(kù)推薦,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • CGLIB代理的使用與原理解析

    CGLIB代理的使用與原理解析

    這篇文章主要介紹了CGLIB代理的使用與原理解析,靜態(tài)代理和JDK 代理模式都要求目標(biāo)對(duì)象是實(shí)現(xiàn)一個(gè)接口,但是有時(shí)候目標(biāo)對(duì)象只是一個(gè)單獨(dú)的對(duì)象,并沒(méi)有實(shí)現(xiàn)任何的接口,這個(gè)時(shí)候可使用目標(biāo)對(duì)象子類(lèi)來(lái)實(shí)現(xiàn)代理,這就是Cglib代理,需要的朋友可以參考下
    2023-09-09
  • Java調(diào)用第三方http接口的常用方式總結(jié)

    Java調(diào)用第三方http接口的常用方式總結(jié)

    這篇文章主要介紹了Java調(diào)用第三方http接口的常用方式總結(jié),具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • SpringBoot整合MongoDB完成增刪改查分頁(yè)查詢(xún)方式

    SpringBoot整合MongoDB完成增刪改查分頁(yè)查詢(xún)方式

    本文介紹了如何在SpringBoot中整合MongoDB,包括依賴(lài)導(dǎo)入、連接配置、實(shí)體類(lèi)創(chuàng)建、增刪改查、分頁(yè)查詢(xún)、時(shí)間范圍查詢(xún)以及基本操作的調(diào)試
    2025-11-11
  • 23種設(shè)計(jì)模式(5) java適配器模式

    23種設(shè)計(jì)模式(5) java適配器模式

    這篇文章主要為大家詳細(xì)介紹了23種設(shè)計(jì)模式之java適配器模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • SpringBoot實(shí)現(xiàn)發(fā)送短信的示例代碼

    SpringBoot實(shí)現(xiàn)發(fā)送短信的示例代碼

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)發(fā)送短信的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能

    Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能

    今天小編就為大家分享一篇關(guān)于Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Spring Boot 校驗(yàn)用戶上傳的圖片文件(兩種方式)

    Spring Boot 校驗(yàn)用戶上傳的圖片文件(兩種方式)

    圖片上傳是現(xiàn)代應(yīng)用中非常常見(jiàn)的一種功能,也是風(fēng)險(xiǎn)比較高的一個(gè)地方,惡意用戶可能會(huì)上傳一些病毒、木馬,本文給大家介紹兩種對(duì)圖片文件進(jìn)行校驗(yàn)的方法,感興趣的朋友一起看看吧
    2023-11-11
  • Java通過(guò)SMS短信平臺(tái)實(shí)現(xiàn)發(fā)短信功能 含多語(yǔ)言

    Java通過(guò)SMS短信平臺(tái)實(shí)現(xiàn)發(fā)短信功能 含多語(yǔ)言

    這篇文章主要為大家詳細(xì)介紹了Java通過(guò)SMS短信平臺(tái)實(shí)現(xiàn)發(fā)短信功能的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-07-07

最新評(píng)論

红桥区| 神木县| 承德市| 临武县| 遂平县| 佛冈县| 黄石市| 阿坝县| 巩留县| 汾西县| 金华市| 光泽县| 南江县| 子洲县| 格尔木市| 五家渠市| 华蓥市| 平阴县| 登封市| 寻乌县| 柏乡县| 连山| 洞口县| 扶绥县| 克山县| 乌兰察布市| 巧家县| 襄樊市| 苍南县| 华蓥市| 临西县| 上犹县| 河北省| 偃师市| 合川市| 湾仔区| 鹤岗市| 进贤县| 尼勒克县| 西林县| 大冶市|