基于Spring安全URL的授权

我想在我的一个spring mvc项目中实现基于URL的授权。在我的spring mvc项目中,我使用的是java配置,我参考了这个网站。https:/www.baeldung.comrole-and-privilege-for-spring-security-registration 来实现基于角色和权限的授权。

所以我创建了以下表来实现。

这是用户表。

enter image description here

这是角色表。

enter image description here

这是角色和权限之间的映射表.

enter image description here

这个是权限表.

enter image description here

以下是Controller方面的代码。

@Controller
@RequestMapping(value={"/user"})
public class UserController {

    @ResponseBody
    @RequestMapping(value={"/userDashboard"},method = RequestMethod.GET)
    public String userDashboard(ModelMap model){
        return "UserDashboard";
    }

    @ResponseBody
    @RequestMapping(value={"/testUser"},method = RequestMethod.GET)
    public String testUser(ModelMap model){
        return "TestUser";
    }

}

以下是实现UserDetailService的代码。

@Service("authService")
@Transactional
public class AuthService implements UserDetailsService {

    @Autowired
    private UserDaoInterface userDaoInterface;

    private static final Logger log = Logger.getLogger(AuthService.class);

    @Override
    public UserDetails loadUserByUsername(String userName) {
        User user = null;
        try {
            user = userDaoInterface.getUserByUserName(userName);
        } catch (Exception e) {
            log.error("AuthService @loadUserByUsername --Exception while fetching user from username",e);
        }

        if(user == null) {
            throw new UsernameNotFoundException("Username not found");
        }

        UserDetails userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(),!user.getIsDeleted(),true,true,true,getAuthorities(user.getRole()));

        log.info("UserService userDetails " + userDetails);

        return userDetails;
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Role role) {  
        return getGrantedAuthorities(getPrivileges(role));
    }

    private List<String> getPrivileges(Role role) {
        List<String> privileges = new ArrayList<>();
        List<Privilege> collection = new ArrayList<>();
        collection.addAll(role.getPrivileges());
        for (Privilege item : collection) {
            privileges.add(item.getName());
        }
        return privileges;
    }

    private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (String privilege : privileges) {
            authorities.add(new SimpleGrantedAuthority(privilege));
        }
        return authorities;
    }
}

弹簧安全配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@ComponentScan("com.project")
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService authService;

    @Autowired
    PersistentTokenRepository tokenRepository;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(authService);
        auth.authenticationProvider(authenticationProvider());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(authService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }

    @Bean
    public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
        return new PersistentTokenBasedRememberMeServices("remember-me", authService, tokenRepository);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests().anyRequest().authenticated()
         .and()
        .formLogin()
        .loginProcessingUrl("/login")
        .defaultSuccessUrl("/login")
        .and()
        .logout().logoutUrl("/logout")
        .logoutSuccessUrl("/")
        .and().csrf()
        .and().rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository).tokenValiditySeconds(86400);
    }
}

当我通过存储在用户表中的凭证登录系统,并尝试访问网址时,如 http:/localhost:8080RestProjectusertestUser。 那么用户被授权访问这个网址,但是按照上面的实现,用户不应该被允许访问这个网址。所以我不明白动态权限如何工作?

解决方案:

要配置url授权,你需要修改以下行数。http.authorizeRequests().anyRequest().authenticated()

http.authorizeRequests()
.antMatchers("someurl").hasAuthority("ROLE_SOMEROLE")
.antMatchers("/**").hasAuthority("ROLE_ADMIN").authenticated()

然而,似乎你想要的是在运行时动态地改变这些。我不确定spring是否允许你这么做。然而,你可以通过改变你的角色结构设计来实现类似的行为。

你需要为你的权限添加一个分组层,并将这些分组变成你的用户角色(这些将被分配给用户)。然后,你授予的权限将是分配给你的角色分组的权限。这样你就可以动态地改变这些组下的权限,而不需要修改代码。

角色权限结构示例(伪java代码):

注意: 角色和组是可以互换的

@Entity
public class Permission {

    private String name;

    private String description;

    ... // getters and setters
}

@Entity
public class Role {

   private String name;

   @ManyToOne
   private List<Permission> permissions;
   ... // getters and setters
}

首先,你需要有一个做某事的url。比方说,它要创建一个新的雇员记录。所以你需要创建一个新的 “createEmployee “权限,并使其成为访问该url所需的权限。这里的想法是创建特定于它所保护的操作的权限。这样一来,你就不必在将来更改权限了。

http.authorizeRequests()
.antMatchers("some-url").hasAuthority("createEmployee")
.antMatchers("/**").hasAuthority("admin").authenticated()

现在,你需要做的就是将 “createEmployee “权限分配给一个职责包括该操作的角色。比如说,它将是 “hiringManager “角色组。

权限被分配给RoleGrouping的例子。

Role hiringManager = new Role("hiringManager");
Permission createPermission = permissionRepository.findByName("createPermission");
hiringManager.getPermissions().add(createPermission);

这只是为了说明问题. 理想情况下,你会在你的应用程序中有一个屏幕,让你在运行时创建组和权限。然后你可以根据自己的需要分配或删除组的权限。

注意,这只是技术方面的一个解决方案。也就是说,即使它不符合你的需求,它也应该指导你想出任何你的业务需求。

希望对你有所帮助!

给TA打赏
共{{data.count}}人
人已打赏
未分类

列表理解

2022-9-13 15:46:36

未分类

CSS Flex硬伤项目

2022-9-13 15:46:38

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索