亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring security中的授權(quán)

 更新時(shí)間:2024年01月09日 10:56:43   作者:ChatYU.  
本篇為大家?guī)?lái)Spring security的授權(quán),首先要理解一些概念,有關(guān)于:權(quán)限、角色、安全上下文、訪(fǎng)問(wèn)控制表達(dá)式、方法級(jí)安全性、訪(fǎng)問(wèn)決策管理器,這篇文章主要介紹了Spring security中的授權(quán),需要的朋友可以參考下

前言

本篇為大家?guī)?lái)Spring security的授權(quán),首先要理解一些概念,有關(guān)于:權(quán)限、角色、安全上下文、訪(fǎng)問(wèn)控制表達(dá)式、方法級(jí)安全性、訪(fǎng)問(wèn)決策管理器

一.授權(quán)的基本介紹

Spring Security 中的授權(quán)分為兩種類(lèi)型:

  • 基于角色的授權(quán):以用戶(hù)所屬角色為基礎(chǔ)進(jìn)行授權(quán),如管理員、普通用戶(hù)等,通過(guò)為用戶(hù)分配角色來(lái)控制其對(duì)資源的訪(fǎng)問(wèn)權(quán)限。
  • 基于資源的授權(quán):以資源為基礎(chǔ)進(jìn)行授權(quán),如 URL、方法等,通過(guò)定義資源所需的權(quán)限,來(lái)控制對(duì)該資源的訪(fǎng)問(wèn)權(quán)限。

Spring Security 提供了多種實(shí)現(xiàn)授權(quán)的機(jī)制,最常用的是使用基于注解的方式,建立起訪(fǎng)問(wèn)資源和權(quán)限之間的映射關(guān)系。

其中最常用的兩個(gè)注解是 @Secured@PreAuthorize@Secured 注解是更早的注解,基于角色的授權(quán)比較適用,@PreAuthorize 基于 SpEL 表達(dá)式的方式,可靈活定義所需的權(quán)限,通常用于基于資源的授權(quán)。

二.修改User配置角色和權(quán)限

方法一.

使用SQL語(yǔ)句的方式查詢(xún)?cè)摻巧臋?quán)限,并且可以對(duì)它進(jìn)行修改

根據(jù)用戶(hù)id查詢(xún)出對(duì)應(yīng)的角色信息

 SELECT
            *
        FROM
            sys_user a,
            sys_user_role b,
            sys_role_module c,
            sys_module d
        WHERE a.id = b.user_id and
            b.role_id=c.role_id and
            c.module_id = d.id and
            a.id=#{id}

根據(jù)用戶(hù)ID查詢(xún)出角色對(duì)應(yīng)的權(quán)限信息

select
	m.url
from
	sys_user u,sys_user_role ur,sys_role r,sys_role_module rm,sys_module m
where
    u.id=ur.userid and ur.roleid=r.roleid and
    r.roleid=rm.roleid and rm.moduleid=m.id and
    u.id=#{userid} and url is not null

但是并不推薦使用這種方法,當(dāng)我們?cè)趯?shí)際開(kāi)發(fā)中,要考慮到不同的數(shù)據(jù)表可能來(lái)自不同的庫(kù)中,使用SQL查詢(xún)時(shí)就會(huì)出現(xiàn)鏈表查詢(xún)不同庫(kù)的表的情況,所以,更多的時(shí)候我們會(huì)使用Java利用不同的操作對(duì)表進(jìn)行依次查詢(xún)作為條件最終得到結(jié)果

方法二.利用Java對(duì)表單一查詢(xún)?nèi)缓笞鳛椴樵?xún)條件,最終查詢(xún)出結(jié)果

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService, UserDetailsService {
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IRoleModuleService roleModuleService;
    @Autowired
    private IModuleService moduleService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = getOne(new QueryWrapper<User>().eq("username", username));
        if(user==null){
            throw new UsernameNotFoundException("用戶(hù)名無(wú)效");
        }
        //查詢(xún)出身份
        //map遍歷所有對(duì)象,返回新的數(shù)據(jù)放到新的集合中
        //filter 過(guò)濾流中的內(nèi)容
        //collect將流中的元素變成一個(gè)集合
        List<Integer> role_ids = userRoleService
                .list(new QueryWrapper<UserRole>().eq("user_id", user.getId()))
                .stream().map(UserRole::getRoleId)
                .collect(Collectors.toList());
        //根據(jù)身份字段查詢(xún)身份對(duì)應(yīng)的名字字段
        List<String> roles = roleService
                .list(new QueryWrapper<Role>())
                .stream().map(Role::getRoleName)
                .collect(Collectors.toList());
        //根據(jù)身份id查詢(xún)具備的權(quán)限id
        List<Integer> module_ids = roleModuleService
                .list(new QueryWrapper<RoleModule>().in("role_id", role_ids))
                .stream().map(RoleModule::getModuleId)
                .collect(Collectors.toList());
        //根據(jù)權(quán)限id查詢(xún)對(duì)應(yīng)的權(quán)限
        List<String> modules = moduleService
                .list(new QueryWrapper<Module>().in("id", module_ids))
                .stream().map(Module::getUrl)
                .collect(Collectors.toList());
        // 將權(quán)限字段加到身份中
        roles.addAll(modules);
        //將當(dāng)前集合內(nèi)容加到權(quán)限字段中
        List<SimpleGrantedAuthority> authorities = roles.stream()
                .map(SimpleGrantedAuthority::new)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        user.setAuthorities(authorities);
        return user;
    }
}

三.SpringSecurity配置類(lèi)

當(dāng)我們想要開(kāi)啟spring方法級(jí)安全時(shí),只需要在任何 @Configuration實(shí)例上使用@EnableGlobalMethodSecurity 注解就能達(dá)到此目的。同時(shí)這個(gè)注解為我們提供了prePostEnabled 、securedEnabledjsr250Enabled 三種不同的機(jī)制來(lái)實(shí)現(xiàn)同一種功能。

修改WebSecurityConfig配置類(lèi),開(kāi)啟基于方法的安全認(rèn)證機(jī)制,也就是說(shuō)在web層的controller啟用注解機(jī)制的安全確認(rèn)。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
    @Autowired
    private UserServiceImpl userDetailsService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        //創(chuàng)建DaoAuthenticationProvider
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        //設(shè)置userDetailsService,基于數(shù)據(jù)庫(kù)方式進(jìn)行身份認(rèn)證
        provider.setUserDetailsService(userDetailsService);
        //配置密碼編碼器
        provider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(provider);
    }
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //antMatchers 匹配對(duì)應(yīng)的路徑
                //permitAll 允許
                .antMatchers("/").permitAll()
                //anyRequest 其余所有請(qǐng)求
                //authenticated 登錄
                .anyRequest().authenticated()
                .and()
                .formLogin()
                //loginPage 登錄頁(yè)面
                .loginPage("/")
                //設(shè)置處理登錄請(qǐng)求的接口
                .loginProcessingUrl("/userLogin")
                //用戶(hù)的數(shù)據(jù)的參數(shù)
                .usernameParameter("username")
                .passwordParameter("password")
                //登錄成功
                .successHandler((req, resp, auth) -> {
                    Object user = auth.getPrincipal();
                    objectMapper
                            .writeValue(resp.getOutputStream(), JsonResponseBody.success(user));
                })
                //登錄失敗
                .failureHandler(myAuthenticationFailureHandler)
                .and()
                .exceptionHandling()
                //權(quán)限不足
                .accessDeniedHandler((req, resp, ex) -> {
                    objectMapper
                            .writeValue(resp.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_ACCESS));
                })
                //沒(méi)有認(rèn)證
                .authenticationEntryPoint((req, resp, ex) -> {
                    objectMapper
                            .writeValue(resp.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));
                })
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/");
        http.csrf().disable();
        return http.build();
    }
}

這里需要注意的是:@EnableGlobalMethodSecurity是Spring Security提供的一個(gè)注解,用于啟用方法級(jí)別的安全性。它可以在任何@Configuration類(lèi)上使用,以啟用Spring Security的方法級(jí)別的安全性功能。它接受一個(gè)或多個(gè)參數(shù),用于指定要使用的安全注解類(lèi)型和其他選項(xiàng)。以下是一些常用的參數(shù)

prePostEnabled:如果設(shè)置為true,則啟用@PreAuthorize@PostAuthorize注解。默認(rèn)值為false

securedEnabled:如果設(shè)置為true,則啟用@Secured注解。默認(rèn)值為false

jsr250Enabled:如果設(shè)置為true,則啟用@RolesAllowed注解。默認(rèn)值為false。

proxyTargetClass:如果設(shè)置為true,則使用CGLIB代理而不是標(biāo)準(zhǔn)的JDK動(dòng)態(tài)代理。默認(rèn)值為false。

使用@EnableGlobalMethodSecurity注解后,可以在應(yīng)用程序中使用Spring Security提供的各種注解來(lái)保護(hù)方法,例如@Secured、@PreAuthorize@PostAuthorize@RolesAllowed。這些注解允許您在方法級(jí)別上定義安全規(guī)則,以控制哪些用戶(hù)可以訪(fǎng)問(wèn)哪些方法。

注解介紹:

注解說(shuō)明
@PreAuthorize用于在方法執(zhí)行之前對(duì)訪(fǎng)問(wèn)進(jìn)行權(quán)限驗(yàn)證
@PostAuthorize用于在方法執(zhí)行之后對(duì)返回結(jié)果進(jìn)行權(quán)限驗(yàn)證
@Secured用于在方法執(zhí)行之前對(duì)訪(fǎng)問(wèn)進(jìn)行權(quán)限驗(yàn)證
@RolesAllowed是Java標(biāo)準(zhǔn)的注解之一,用于在方法執(zhí)行之前對(duì)訪(fǎng)問(wèn)進(jìn)行權(quán)限驗(yàn)證

 四.管理控制Controller層的權(quán)限

@Controller
public class IndexController {
    @RequestMapping("/")
    public String toLogin() {
        return "login";
    }
    @RequestMapping("/userLogin")
    public String userLogin() {
        return "index";
    }
    @RequestMapping("/index")
    public String toIndex() {
        return "index";
    }
    @RequestMapping("/noAccess")
    public String noAccess() {
        return "accessDenied";
    }
    @ResponseBody
    @RequestMapping("/order_add")
    @PreAuthorize("hasAuthority('order:manager:add')")
    public String order_add() {
        return "訂單新增";
    }
    @ResponseBody
    @PreAuthorize("hasAuthority('book:manager:add')")
    @RequestMapping("/book_add")
    public String book_add() {
        return "書(shū)本新增";
    }
}

在當(dāng)前登錄的用戶(hù)必須擁有當(dāng)前的權(quán)限字段才能進(jìn)行訪(fǎng)問(wèn),例如:book:manager:add

五.異常處理

AccessDeniedHandler是Spring Security提供的一個(gè)接口,用于處理訪(fǎng)問(wèn)被拒絕的情況。當(dāng)用戶(hù)嘗試訪(fǎng)問(wèn)受保護(hù)資源但沒(méi)有足夠的權(quán)限時(shí),Spring Security會(huì)調(diào)用AccessDeniedHandler來(lái)處理這種情況。

AccessDeniedHandler接口只有一個(gè)方法handle(),該方法接收HttpServletRequestHttpServletResponseAccessDeniedException三個(gè)參數(shù)。在handle()方法中,可以自定義響應(yīng)的內(nèi)容,例如返回一個(gè)自定義的錯(cuò)誤頁(yè)面或JSON響應(yīng)。

創(chuàng)建AccessDeniedHandlerImpl類(lèi)并實(shí)現(xiàn)AccessDeniedHandler接口,實(shí)現(xiàn)自定義的JSON響應(yīng)。例如:

package com.yu.security.resp;
import lombok.Getter;
@Getter
public enum JsonResponseStatus {
    OK(200, "OK"),
    UN_KNOWN(500, "未知錯(cuò)誤"),
    RESULT_EMPTY(1000, "查詢(xún)結(jié)果為空"),
    NO_ACCESS(3001, "沒(méi)有權(quán)限"),
    NO_LOGIN(4001, "沒(méi)有登錄"),
    LOGIN_FAILURE(5001, "登錄失敗"),
    ;
    private final Integer code;
    private final String msg;
    JsonResponseStatus(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

單獨(dú)寫(xiě)一個(gè)接口進(jìn)行實(shí)現(xiàn),并將出現(xiàn)異常后的操作在里面實(shí)現(xiàn)

package com.yu.security.config;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yu.security.pojo.User;
import com.yu.security.resp.JsonResponseBody;
import com.yu.security.resp.JsonResponseStatus;
import com.yu.security.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Autowired
    private ObjectMapper objectMapper;
    // 在redis中定義一個(gè)鍵當(dāng)?shù)卿浭∈蔷蛯?duì)那個(gè)鍵的值進(jìn)行加一
    //如果大于三就鎖住
    @Autowired
    private IUserService userService;
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        if(1==2){
            User user = userService.getOne(new QueryWrapper<User>().eq("username", request.getParameter("username")));
            user.setAccountNonLocked(false);
            userService.updateById(user);
        }
        objectMapper.writeValue(response.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.LOGIN_FAILURE));
    }
}

在當(dāng)前例子中:我們通過(guò)在配置類(lèi)引入當(dāng)前接口,并實(shí)現(xiàn)當(dāng)前接口,在實(shí)現(xiàn)類(lèi)中,對(duì)登錄失敗進(jìn)行 對(duì)應(yīng)的操作,在Redis中定義一個(gè)鍵當(dāng)?shù)卿浭∈蔷蛯?duì)那個(gè)鍵的值進(jìn)行加一,如果大于三就對(duì)當(dāng)前賬號(hào)進(jìn)行凍結(jié)

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

相關(guān)文章

  • Spring?web開(kāi)發(fā)教程之Request獲取3種方式

    Spring?web開(kāi)發(fā)教程之Request獲取3種方式

    這篇文章主要給大家介紹了關(guān)于Spring?web開(kāi)發(fā)教程之Request獲取3種方式的相關(guān)資料,request對(duì)象是從客戶(hù)端向服務(wù)器發(fā)出請(qǐng)求,包括用戶(hù)提交的信息以及客戶(hù)端的一些信息,需要的朋友可以參考下
    2023-11-11
  • Java8內(nèi)存模型PermGen Metaspace實(shí)例解析

    Java8內(nèi)存模型PermGen Metaspace實(shí)例解析

    這篇文章主要介紹了Java8內(nèi)存模型PermGen Metaspace實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • JVM?中的?returnAddress過(guò)程詳解

    JVM?中的?returnAddress過(guò)程詳解

    JVM的畢竟是個(gè)虛擬機(jī),是一種規(guī)范,雖說(shuō)符合馮諾依曼的計(jì)算機(jī)設(shè)計(jì)理念,但是他并不是實(shí)體計(jì)算機(jī),所以他的組成也不是什么存儲(chǔ)器,控制器,運(yùn)算 器,輸入輸出設(shè)備,本文給大家介紹JVM?中的?returnAddress,感興趣的朋友一起看看吧
    2022-04-04
  • 如何在Java中判斷兩個(gè)Long類(lèi)型是否相等

    如何在Java中判斷兩個(gè)Long類(lèi)型是否相等

    這篇文章主要介紹了如何在Java中判斷兩個(gè)Long類(lèi)型是否相等,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的?參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • redis 使用lettuce 啟動(dòng)內(nèi)存泄漏錯(cuò)誤的解決方案

    redis 使用lettuce 啟動(dòng)內(nèi)存泄漏錯(cuò)誤的解決方案

    這篇文章主要介紹了redis 使用lettuce 啟動(dòng)內(nèi)存泄漏錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 詳解java配置文件的路徑問(wèn)題

    詳解java配置文件的路徑問(wèn)題

    這篇文章主要介紹了詳解java配置文件的路徑問(wèn)題的相關(guān)資料,這里對(duì)絕對(duì)路徑及相對(duì)路徑和classpath 類(lèi)文件路徑進(jìn)行詳細(xì)介紹,需要的朋友可以參考下
    2017-07-07
  • Java 重寫(xiě)時(shí)應(yīng)當(dāng)遵守的 11 條規(guī)則

    Java 重寫(xiě)時(shí)應(yīng)當(dāng)遵守的 11 條規(guī)則

    這篇文章主要介紹了Java 重寫(xiě)時(shí)應(yīng)當(dāng)遵守的 11 條規(guī)則,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 基于Java解析國(guó)密數(shù)字證書(shū)的操作方法

    基于Java解析國(guó)密數(shù)字證書(shū)的操作方法

    在Java環(huán)境中解析使用國(guó)密算法(如SM3WITHSM2)的數(shù)字證書(shū)可能遇到挑戰(zhàn),使用BouncyCastle加密庫(kù)可以解決Java標(biāo)準(zhǔn)庫(kù)無(wú)法識(shí)別國(guó)密算法橢圓曲線(xiàn)的問(wèn)題,成功解析國(guó)密數(shù)字證書(shū),添加BouncyCastle依賴(lài)并修改代碼,使其支持國(guó)密算法,即可解析采用SM3WITHSM2算法的數(shù)字證書(shū)
    2024-09-09
  • Java并發(fā)包之CopyOnWriteArrayList類(lèi)的深入講解

    Java并發(fā)包之CopyOnWriteArrayList類(lèi)的深入講解

    這篇文章主要給大家介紹了關(guān)于Java并發(fā)包之CopyOnWriteArrayList類(lèi)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java從零編寫(xiě)吃貨聯(lián)盟訂餐系統(tǒng)全程講解

    Java從零編寫(xiě)吃貨聯(lián)盟訂餐系統(tǒng)全程講解

    這篇文章主要介紹了Java訂餐系統(tǒng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-12-12

最新評(píng)論