国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

基于 Spring Session & Spring Security 微服務(wù)權(quán)限控制

clasnake / 1795人閱讀

摘要:構(gòu)造函數(shù)的第一個(gè)參數(shù)是對(duì)象,所以可以自定義緩存對(duì)象。在微服務(wù)各個(gè)模塊獲取用戶的這些信息的方法如下略權(quán)限控制啟用基于方法的權(quán)限注解簡(jiǎn)單權(quán)限校驗(yàn)例如,刪除角色的接口,僅允許擁有權(quán)限的用戶訪問(wèn)。

微服務(wù)架構(gòu)

網(wǎng)關(guān):路由用戶請(qǐng)求到指定服務(wù),轉(zhuǎn)發(fā)前端 Cookie 中包含的 Session 信息;

用戶服務(wù):用戶登錄認(rèn)證(Authentication),用戶授權(quán)(Authority),用戶管理(Redis Session Management)

其他服務(wù):依賴 Redis 中用戶信息進(jìn)行接口請(qǐng)求驗(yàn)證

用戶 - 角色 - 權(quán)限表結(jié)構(gòu)設(shè)計(jì)

權(quán)限表

權(quán)限表最小粒度的控制單個(gè)功能,例如用戶管理、資源管理,表結(jié)構(gòu)示例:

id authority description
1 ROLE_ADMIN_USER 管理所有用戶
2 ROLE_ADMIN_RESOURCE 管理所有資源
3 ROLE_A_1 訪問(wèn) ServiceA 的某接口的權(quán)限
4 ROLE_A_2 訪問(wèn) ServiceA 的另一個(gè)接口的權(quán)限
5 ROLE_B_1 訪問(wèn) ServiceB 的某接口的權(quán)限
6 ROLE_B_2 訪問(wèn) ServiceB 的另一個(gè)接口的權(quán)限

角色 - 權(quán)限表

自定義角色,組合各種權(quán)限,例如超級(jí)管理員擁有所有權(quán)限,表結(jié)構(gòu)示例:

id name authority_ids
1 超級(jí)管理員 1,2,3,4,5,6
2 管理員A 3,4
3 管理員B 5,6
4 普通用戶 NULL

用戶 - 角色表

用戶綁定一個(gè)或多個(gè)角色,即分配各種權(quán)限,示例表結(jié)構(gòu):

user_id role_id
1 1
1 4
2 2
用戶服務(wù)設(shè)計(jì)

Maven 依賴(所有服務(wù))

        
        
            org.springframework.boot
            spring-boot-starter-security
        

        
        
            org.springframework.session
            spring-session-data-redis
        

應(yīng)用配置 application.yml 示例:

# Spring Session 配置
spring.session.store-type=redis
server.servlet.session.persistent=true
server.servlet.session.timeout=7d
server.servlet.session.cookie.max-age=7d

# Redis 配置
spring.redis.host=
spring.redis.port=6379

# MySQL 配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://:3306/test
spring.datasource.username=
spring.datasource.password=

用戶登錄認(rèn)證(authentication)與授權(quán)(authority)

@Slf4j
public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final UserService userService;

    CustomAuthenticationFilter(String defaultFilterProcessesUrl, UserService userService) {
        super(new AntPathRequestMatcher(defaultFilterProcessesUrl, HttpMethod.POST.name()));
        this.userService = userService;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        JSONObject requestBody = getRequestBody(request);
        String username = requestBody.getString("username");
        String password = requestBody.getString("password");
        UserDO user = userService.getByUsername(username);
        if (user != null && validateUsernameAndPassword(username, password, user)){
            // 查詢用戶的 authority
            List userAuthorities = userService.getSimpleGrantedAuthority(user.getId());
            return new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities);
        }
        throw new AuthenticationServiceException("登錄失敗");
    }

    /**
     * 獲取請(qǐng)求體
     */
    private JSONObject getRequestBody(HttpServletRequest request) throws AuthenticationException{
        try {
            StringBuilder stringBuilder = new StringBuilder();
            InputStream inputStream = request.getInputStream();
            byte[] bs = new byte[StreamUtils.BUFFER_SIZE];
            int len;
            while ((len = inputStream.read(bs)) != -1) {
                stringBuilder.append(new String(bs, 0, len));
            }
            return JSON.parseObject(stringBuilder.toString());
        } catch (IOException e) {
            log.error("get request body error.");
        }
        throw new AuthenticationServiceException(HttpRequestStatusEnum.INVALID_REQUEST.getMessage());
    }

    /**
     * 校驗(yàn)用戶名和密碼
     */
    private boolean validateUsernameAndPassword(String username, String password, UserDO user) throws AuthenticationException {
         return username == user.getUsername() && password == user.getPassword();
    }

}
@EnableWebSecurity
@AllArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String LOGIN_URL = "/user/login";

    private static final String LOGOUT_URL = "/user/logout";

    private final UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(LOGIN_URL).permitAll()
                .anyRequest().authenticated()
                .and()
                .logout().logoutUrl(LOGOUT_URL).clearAuthentication(true).permitAll()
                .and()
                .csrf().disable();

        http.addFilterAt(bipAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .rememberMe().alwaysRemember(true);
    }

    /**
     * 自定義認(rèn)證過(guò)濾器
     */
    private CustomAuthenticationFilter customAuthenticationFilter() {
        CustomAuthenticationFilter authenticationFilter = new CustomAuthenticationFilter(LOGIN_URL, userService);
        return authenticationFilter;
    }

}
其他服務(wù)設(shè)計(jì)

應(yīng)用配置 application.yml 示例:

# Spring Session 配置
spring.session.store-type=redis

# Redis 配置
spring.redis.host=
spring.redis.port=6379

全局安全配置

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }

}
用戶認(rèn)證信息獲取

用戶通過(guò)用戶服務(wù)登錄成功后,用戶信息會(huì)被緩存到 Redis,緩存的信息與 CustomAuthenticationFilterattemptAuthentication() 方法返回的對(duì)象有關(guān),如上所以,返回的對(duì)象是 new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities),即 Redis 緩存了用戶的 ID 和用戶的權(quán)力(authorities)。

UsernamePasswordAuthenticationToken 構(gòu)造函數(shù)的第一個(gè)參數(shù)是 Object 對(duì)象,所以可以自定義緩存對(duì)象。

在微服務(wù)各個(gè)模塊獲取用戶的這些信息的方法如下:

    @GetMapping()
    public WebResponse test(@AuthenticationPrincipal UsernamePasswordAuthenticationToken authenticationToken){
       // 略
    }
權(quán)限控制

啟用基于方法的權(quán)限注解

@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

簡(jiǎn)單權(quán)限校驗(yàn)

例如,刪除角色的接口,僅允許擁有 ROLE_ADMIN_USER 權(quán)限的用戶訪問(wèn)。

    /**
     * 刪除角色
     */
    @PostMapping("/delete")
    @PreAuthorize("hasRole("ADMIN_USER")")
    public WebResponse deleteRole(@RequestBody RoleBean roleBean){
          // 略
    }
@PreAuthorize("hasRole("")") 可作用于微服務(wù)中的各個(gè)模塊

自定義權(quán)限校驗(yàn)

如上所示,hasRole() 方法是 Spring Security 內(nèi)嵌的,如需自定義,可以使用 Expression-Based Access Control,示例:

/**
 * 自定義校驗(yàn)服務(wù)
 */
@Service
public class CustomService{

    public boolean check(UsernamePasswordAuthenticationToken authenticationToken, String extraParam){
          // 略
    }

}
    /**
     * 刪除角色
     */
    @PostMapping()
    @PreAuthorize("@customService.check(authentication, #userBean.username)")
    public WebResponse custom(@RequestBody UserBean userBean){
          // 略
    }
authentication 屬于內(nèi)置對(duì)象, # 獲取入?yún)⒌闹?/pre>

任意用戶權(quán)限動(dòng)態(tài)修改

原理上,用戶的權(quán)限信息保存在 Redis 中,修改用戶權(quán)限就需要操作 Redis,示例:

@Service
@AllArgsConstructor
public class HttpSessionService  {

    private final FindByIndexNameSessionRepository sessionRepository;

    /**
     * 重置用戶權(quán)限
     */
    public void resetAuthorities(Long userId, List authorities){
        UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken(userId, null, authorities);
        Map redisSessionMap = sessionRepository.findByPrincipalName(String.valueOf(userId));
        redisSessionMap.values().forEach(session -> {
            SecurityContextImpl securityContext = session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
            securityContext.setAuthentication(newToken);
            session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
            sessionRepository.save(session);
        });
    }

}

修改用戶權(quán)限,僅需調(diào)用 httpSessionService.resetAuthorities() 方法即可,實(shí)時(shí)生效。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75029.html

相關(guān)文章

  • Spring Security

    摘要:框架具有輕便,開(kāi)源的優(yōu)點(diǎn),所以本譯見(jiàn)構(gòu)建用戶管理微服務(wù)五使用令牌和來(lái)實(shí)現(xiàn)身份驗(yàn)證往期譯見(jiàn)系列文章在賬號(hào)分享中持續(xù)連載,敬請(qǐng)查看在往期譯見(jiàn)系列的文章中,我們已經(jīng)建立了業(yè)務(wù)邏輯數(shù)據(jù)訪問(wèn)層和前端控制器但是忽略了對(duì)身份進(jìn)行驗(yàn)證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護(hù)REST API 重拾后端之Spring Boot(一):REST API的搭建...

    keelii 評(píng)論0 收藏0
  • 不用 Spring Security 可否?試試這個(gè)小而美的安全框架

    摘要:寫(xiě)在前面在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問(wèn)題。用戶的合法性與數(shù)據(jù)的可見(jiàn)性是數(shù)據(jù)安全中非常重要的一部分。 寫(xiě)在前面 在一款應(yīng)用的整個(gè)生命周期,我們都會(huì)談及該應(yīng)用的數(shù)據(jù)安全問(wèn)題。用戶的合法性與數(shù)據(jù)的可見(jiàn)性是數(shù)據(jù)安全中非常重要的一部分。但是,一方面,不同的應(yīng)用對(duì)于數(shù)據(jù)的合法性和可見(jiàn)性要求的維度與粒度都有所區(qū)別;另一方面,以當(dāng)前微服務(wù)、多服務(wù)的架構(gòu)方式,如何共享Sessi...

    toddmark 評(píng)論0 收藏0
  • 深入理解Spring Cloud與服務(wù)構(gòu)建【二】 - 2.2 Spring Cloud

    摘要:負(fù)載均衡組件是一個(gè)負(fù)載均衡組件,它通常和配合使用。和配合,很容易做到負(fù)載均衡,將請(qǐng)求根據(jù)負(fù)載均衡策略分配到不同的服務(wù)實(shí)例中。和配合,在消費(fèi)服務(wù)時(shí)能夠做到負(fù)載均衡。在默認(rèn)的情況下,和相結(jié)合,能夠做到負(fù)載均衡智能路由。 2.2.1 簡(jiǎn)介 Spring Cloud 是基于 Spring Boot 的。 Spring Boot 是由 Pivotal 團(tuán)隊(duì)提供的全新 Web 框架, 它主要的特點(diǎn)...

    Rocko 評(píng)論0 收藏0
  • 讓ERP的服務(wù)更開(kāi)放! ——用服務(wù)架構(gòu)搭建的一套基于EBS的API服務(wù)系統(tǒng)

    摘要:每個(gè)服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)與服務(wù)間采用輕量級(jí)的通信機(jī)制互相溝通通常是基于的。在微服務(wù)架構(gòu)下,故障會(huì)被隔離在單個(gè)服務(wù)中。 1. 源碼下載地址 源碼鏈接: https://github.com/samt007/xy... 這是用Spring Cloud微服務(wù)架構(gòu)搭建的一套基于EBS的API服務(wù)系統(tǒng)如對(duì)本文有任何的疑問(wèn),請(qǐng)聯(lián)系我:samt007@qq.com 2. Introduc...

    JouyPub 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<