Jhipster权限控制设计及改进

一、原有权限系统设计

在这里插入图片描述

1.后端API访问控制

在SecurityConfiguartion.java的configure方法中配置

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
                .authenticationEntryPoint(problemSupport)
                .accessDeniedHandler(problemSupport)
        .and()
            .headers()
            .contentSecurityPolicy("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:")
        .and()
            .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
        .and()
            .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'")
        .and()
            .frameOptions()
            .deny()
        .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/account/reset-password/init").permitAll()
            .antMatchers("/api/account/reset-password/finish").permitAll()
            .antMatchers("/api/**").authenticated()
            .antMatchers("/management/health").permitAll()
            .antMatchers("/management/info").permitAll()
            .antMatchers("/management/prometheus").permitAll()
            .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .and()
            .httpBasic()
        .and()
            .apply(securityConfigurerAdapter());
        // @formatter:on
    }

URL匹配权限有三种:

  • permitAll :允许任何人
  • authenticated :允许认证的用户访问
  • hasAuthority : 允许指定权限的用户访问

2.后端URL动词访问控制

在Restfull接口文件中,以UserResource.java为例,添加PreAuthorize注释

    /**
     * {@code DELETE /users/:login} : delete the "login" User.
     *
     * @param login the login of the user to delete.
     * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
     */
    @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
    @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
    public ResponseEntity<Void> deleteUser(@PathVariable String login) {
        log.debug("REST request to delete User: {}", login);
        userService.deleteUser(login);
        return ResponseEntity.noContent().headers(HeaderUtil.createAlert(applicationName,  "userManagement.deleted", login)).build();
    }

3.后端Entity访问控制

通过 SecurityUtils获取登录用户信息,只能访问有特定信息的entity

@GetMapping("/bank-accounts/{id}")
@Timed
public ResponseEntity<BankAccountDTO> getBankAccount(@PathVariable Long id) {
    log.debug("REST request to get BankAccount : {}", id);
    Optional<BankAccountDTO> bankAccountDTO = bankAccountRepository.findById(id)
        .map(bankAccountMapper::toDto);

    // Return 404 if the entity is not owned by the connected user
    Optional<String> userLogin = SecurityUtils.getCurrentUserLogin();
    if (bankAccountDTO.isPresent() &&
        userLogin.isPresent() &&
        userLogin.get().equals(bankAccountDTO.get().getUserLogin())) {
        return ResponseUtil.wrapOrNotFound(bankAccountDTO);
    } else {
        return ResponseEntity.notFound().build();
    }
}

改进:采用注释的方式

  1. @PostAuthorize (“returnObject.type == authentication.name”)

DomainUserDetailsService

SecurityUtils:
isCurrentUserInRole
isAuthenticated
getCurrentUserLogin

4.前端module访问控制

Angular每个module都有modulename.route.ts文件,包含路由信息

export const bankAccountPopupRoute: Routes = [
    {
        path: 'bank-account/:id/delete',
        component: BankAccountDeletePopupComponent,
        resolve: {
            bankAccount: BankAccountResolve
        },
        data: {
            authorities: ['ROLE_USER'],
            pageTitle: 'jhipsterSampleApplicationApp.bankAccount.home.title'
        },
        canActivate: [UserRouteAccessService],
        outlet: 'popup'
    }
];

具体实现由user-route-access-service.ts的
canActivate调用checkLogin实现权限的控制目的

5.前端界面元素访问控制

使用jhiHasAnyAuthority属性

<button *jhiHasAnyAuthority="'ROLE_ADMIN'"
        type="submit"
        [routerLink]="['/', { outlets: { popup: 'bank-account/'+ bankAccount.id + '/delete'} }]"
        replaceUrl="true"
        queryParamsHandling="merge"
        class="btn btn-danger btn-sm">
    <fa-icon [icon]="'times'"></fa-icon>
    <span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span>
</button>

其实质是通过has-any-authority.directive.ts的updateView函数,调用this.accountService.hasAnyAuthority实现
6.前端ts访问控制
this.accountService.hasAnyAuthority(‘ROLE_ADMIN’)

二、权限改进设计

1.后端权限控制设计

a、定制权限访问控制服务,通过PreAuthorize控制访问
服务

@Service
public class SecurityService {
  
   public boolean hasAccess(int parameter) {
       return parameter == 1;
   }
}

访问控制

@PreAuthorize("@securityService.hasAccess(#id)")
Message findOne(Long id);

b、Secured Filter拦截
通过继承常用的FilterSecurityInterceptor方式实现

推广:基于JHipster改进系统生成的应用演示

2.前端权限控制设计改进

a、定制权限访问控制服务,通过PreAuthorize控制访问

标题

@Injectable({ providedIn: 'root' })
export class UserRouteAccessService implements CanActivate {
  constructor(
    private router: Router,
    private loginModalService: LoginModalService,
    private accountService: AccountService,
    private stateStorageService: StateStorageService
  ) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    const authorities = route.data['authorities'];
    // We need to call the checkLogin / and so the accountService.identity() function, to ensure,
    // that the client has a principal too, if they already logged in by the server.
    // This could happen on a page refresh.
    return this.checkLogin(authorities, state.url);
  }

  checkLogin(authorities: string[], url: string): Observable<boolean> {
    return this.accountService.identity().pipe(
      map(account => {
        if (!authorities || authorities.length === 0) {
          return true;
        }

        if (account) {
          this.accountService.authenticate(account);
          const hasAnyAuthority = this.accountService.hasAnyAuthority(authorities);
          if (hasAnyAuthority) {
            return true;
          }
          if (isDevMode()) {
            console.error('User has not any of required authorities: ', authorities);
          }
          this.router.navigate(['accessdenied']);
          return false;
        }

        this.stateStorageService.storeUrl(url);
        this.router.navigate(['']);
        this.loginModalService.open();
        return false;
      })
    );
  }
}

推广:基于JHipster改进系统生成的应用演示

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值