欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring security中的授權(quán)

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

前言

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

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

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

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

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

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

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

方法一.

使用SQL語句的方式查詢該角色的權(quán)限,并且可以對它進(jìn)行修改

根據(jù)用戶id查詢出對應(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ù)用戶ID查詢出角色對應(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)我們在實(shí)際開發(fā)中,要考慮到不同的數(shù)據(jù)表可能來自不同的庫中,使用SQL查詢時(shí)就會(huì)出現(xiàn)鏈表查詢不同庫的表的情況,所以,更多的時(shí)候我們會(huì)使用Java利用不同的操作對表進(jìn)行依次查詢作為條件最終得到結(jié)果

方法二.利用Java對表單一查詢?nèi)缓笞鳛椴樵儣l件,最終查詢出結(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("用戶名無效");
        }
        //查詢出身份
        //map遍歷所有對象,返回新的數(shù)據(jù)放到新的集合中
        //filter 過濾流中的內(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ù)身份字段查詢身份對應(yīng)的名字字段
        List<String> roles = roleService
                .list(new QueryWrapper<Role>())
                .stream().map(Role::getRoleName)
                .collect(Collectors.toList());
        //根據(jù)身份id查詢具備的權(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查詢對應(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配置類

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

修改WebSecurityConfig配置類,開啟基于方法的安全認(rèn)證機(jī)制,也就是說在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ù)庫方式進(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 匹配對應(yīng)的路徑
                //permitAll 允許
                .antMatchers("/").permitAll()
                //anyRequest 其余所有請求
                //authenticated 登錄
                .anyRequest().authenticated()
                .and()
                .formLogin()
                //loginPage 登錄頁面
                .loginPage("/")
                //設(shè)置處理登錄請求的接口
                .loginProcessingUrl("/userLogin")
                //用戶的數(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));
                })
                //沒有認(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類上使用,以啟用Spring Security的方法級(jí)別的安全性功能。它接受一個(gè)或多個(gè)參數(shù),用于指定要使用的安全注解類型和其他選項(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提供的各種注解來保護(hù)方法,例如@Secured、@PreAuthorize、@PostAuthorize@RolesAllowed。這些注解允許您在方法級(jí)別上定義安全規(guī)則,以控制哪些用戶可以訪問哪些方法。

注解介紹:

注解說明
@PreAuthorize用于在方法執(zhí)行之前對訪問進(jìn)行權(quán)限驗(yàn)證
@PostAuthorize用于在方法執(zhí)行之后對返回結(jié)果進(jìn)行權(quán)限驗(yàn)證
@Secured用于在方法執(zhí)行之前對訪問進(jìn)行權(quán)限驗(yàn)證
@RolesAllowed是Java標(biāo)準(zhǔn)的注解之一,用于在方法執(zhí)行之前對訪問進(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 "書本新增";
    }
}

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

五.異常處理

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

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

創(chuàng)建AccessDeniedHandlerImpl類并實(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, "查詢結(jié)果為空"),
    NO_ACCESS(3001, "沒有權(quán)限"),
    NO_LOGIN(4001, "沒有登錄"),
    LOGIN_FAILURE(5001, "登錄失敗"),
    ;
    private final Integer code;
    private final String msg;
    JsonResponseStatus(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

單獨(dú)寫一個(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ù)卿浭∈蔷蛯δ莻€(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)前例子中:我們通過在配置類引入當(dāng)前接口,并實(shí)現(xiàn)當(dāng)前接口,在實(shí)現(xiàn)類中,對登錄失敗進(jìn)行 對應(yīng)的操作,在Redis中定義一個(gè)鍵當(dāng)?shù)卿浭∈蔷蛯δ莻€(gè)鍵的值進(jìn)行加一,如果大于三就對當(dāng)前賬號(hào)進(jìn)行凍結(jié)

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

相關(guān)文章

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

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

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

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

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

    JVM?中的?returnAddress過程詳解

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

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

    這篇文章主要介紹了如何在Java中判斷兩個(gè)Long類型是否相等,文章圍繞主題展開詳細(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à)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 詳解java配置文件的路徑問題

    詳解java配置文件的路徑問題

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

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

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

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

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

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

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

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

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

最新評論