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

解決Spring Security的權(quán)限配置不生效問題

 更新時(shí)間:2022年03月12日 15:44:29   作者:varz  
這篇文章主要介紹了解決Spring Security的權(quán)限配置不生效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring Security權(quán)限配置不生效

在集成Spring Security做接口權(quán)限配置時(shí),在給用戶配置的權(quán)限后,還是一直顯示“無權(quán)限”或者"權(quán)限不足"。 

1、不生效的例子 

接口

@RequestMapping("/admin")
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public String printAdmin() {
        return "如果你看見這句話,說明你有ROLE_ADMIN角色";
    }
    @RequestMapping("/user")
    @ResponseBody
    @PreAuthorize("hasRole('USER')")
    public String printUser() {
        return "如果你看見這句話,說明你有ROLE_USER角色";
    }

SecurityConfig

	.and()
      .authorizeRequests()
      .antMatchers("/user").hasAnyRole("USER") 
      .antMatchers("/admin").hasAnyRole("ADMIN")
      .anyRequest().authenticated() //必須授權(quán)才能范圍

用戶攜帶權(quán)限

在這里插入圖片描述

2、解決辦法

經(jīng)測(cè)試,只有用戶攜帶權(quán)限的字段為 “ROLE_” + 接口/配置 中的權(quán)限字段,才能控制生效,舉例:

將上面的用戶攜帶權(quán)限改為

在這里插入圖片描述

Spring Security動(dòng)態(tài)配置權(quán)限

導(dǎo)入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.22</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    <version>5.1.46</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

相關(guān)配置

application.properties

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/javaboy?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

實(shí)體類User,Role,Menu

這里要實(shí)現(xiàn)UserDetails接口,這個(gè)接口好比一個(gè)規(guī)范。防止開發(fā)者定義的密碼變量名各不相同,從而導(dǎo)致springSecurity不知道哪個(gè)方法是你的密碼

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roleList;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roleList) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Boolean getEnabled() {
        return enabled;
    }
    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
    public Boolean getLocked() {
        return locked;
    }
    public void setLocked(Boolean locked) {
        this.locked = locked;
    }
    public List<Role> getRoleList() {
        return roleList;
    }
    public void setRoleList(List<Role> roleList) {
        this.roleList = roleList;
    }
}
public class Role {
    private Integer id;
    private String name;
    private String nameZh;
...
}
public class Menu {
    private Integer id;
    private String pattern;
    private List<Role> roles;
...
}

創(chuàng)建UserMapper類&&UserMapper.xml

和MenuMapper類&&MenuMapperxml

UserMapper

@Mapper
public interface UserMapper {
? ? User getUserByName(String name);
? ? List<Role> getRoleById(Integer id);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qwl.mysecuritydy.mapper.UserMapper">
? ? <select id="getUserByName" resultType="com.qwl.mysecuritydy.bean.User">
? ? ? ? select * from user where username= #{name}
? ? </select>
? ? <select id="getRoleById" resultType="com.qwl.mysecuritydy.bean.Role">
? ? ? ? select * from role where id in (select rid from user_role where uid = #{uid})
? ? </select>
</mapper>

MenuMapper

@Mapper
public interface MenuMapper {
? ? List<Menu> getMenus();
}

MemuMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qwl.mysecuritydy.mapper.MenuMapper">
? ? <resultMap id="menus_map" type="com.qwl.mysecuritydy.bean.Menu">
? ? ? ? <id property="id" column="id"/>
? ? ? ? <result property="pattern" column="pattern"/>
? ? ? ? <collection property="roles" ofType="com.qwl.mysecuritydy.bean.Role">
? ? ? ? ? ? <id property="id" column="rid"/>
? ? ? ? ? ? <result property="name" column="rname"/>
? ? ? ? ? ? <result property="nameZh" column="rnameZh"/>
? ? ? ? </collection>
? ? </resultMap>
? ? <select id="getMenus" resultMap="menus_map">
? ? ? ? select m.*,r.id as rid,r.name as rname,r.nameZh as rnameZh from menu_role mr left join
? ? ? ? menu m on mr.mid = m.id left join role r on mr.rid = r.id
? ? </select>
</mapper>

創(chuàng)建UserService MenuService

創(chuàng)建UserService實(shí)現(xiàn)UserServiceDetails接口

@Service
public class UserService implements UserDetailsService {
? ? @Autowired
? ? private UserMapper userMapper;
? ? @Override
? ? public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
? ? ? ? User user = userMapper.getUserByName(username);
? ? ? ? if(user ==null){
? ? ? ? ? ? throw new UsernameNotFoundException("用戶名不存在");
? ? ? ? }
? ? ? ? user.setRoleList(userMapper.getRoleById(user.getId()));
? ? ? ? return user;
? ? }
}

創(chuàng)建MenuService

@Service
public class MenuService {
? ? @Autowired
? ? private MenuMapper menuMapper;
? ? public List<Menu> getMenus() {return menuMapper.getMenus();}
}

創(chuàng)建CustomFilterInvocationSecurityMetadataSource

實(shí)現(xiàn)接口FilterInvocationSecurityMetadataSource

注:加@comppent注解,把自定義類注冊(cè)成spring組件

supports返回值設(shè)成true表示支持

重寫getAttributes()方法

  • invacation 調(diào)用 ,求助
  • metadata 元數(shù)據(jù)
@Component
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
? ? //ant風(fēng)格的路徑匹配器
? ? AntPathMatcher pathMatcher = new AntPathMatcher();
? ? @Autowired
? ? private MenuService menuService;
?? ??? ?//supports返回值設(shè)成true表示支持
? ? @Override
? ? public boolean supports(Class<?> aClass) {
? ? ? ? return true;
? ? }
? ? @Override
? ? public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
? ? ? ? //獲取當(dāng)前用戶請(qǐng)求的url
? ? ? ? String requestUrl=((FilterInvocation) object).getRequestUrl();
? ? ? ? //數(shù)據(jù)庫中查詢出所有的路徑
? ? ? ? List<Menu> menus ?=menuService.getMenus();
? ? ? ? for (Menu menu : menus) {
? ? ? ? ? ? //判斷用戶請(qǐng)求的url和數(shù)據(jù)庫的url是否能匹配的上
? ? ? ? ? ? if (pathMatcher.match(menu.getPattern(), requestUrl)) {
? ? ? ? ? ? ? ? List<Role> roles =menu.getRoles();
? ? ? ? ? ? ? ? String[] roleStr = new String[roles.size()];
? ? ? ? ? ? ? ? for (int i = 0; i < roles.size(); i++) {
? ? ? ? ? ? ? ? ? ? roleStr[i]=roles.get(i).getName();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //將篩選的url路徑所具備的角色返回回去
? ? ? ? ? ? ? ? return SecurityConfig.createList(roleStr);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //如果沒有匹配上就返回一個(gè)默認(rèn)的角色,作用好比作一個(gè)標(biāo)記
? ? ? ? return SecurityConfig.createList("ROLE_def");
? ? }
? ? @Override
? ? public Collection<ConfigAttribute> getAllConfigAttributes() {
? ? ? ? return null;
? ? }
}

創(chuàng)建CustomAccessDecisionManager

實(shí)現(xiàn)AccessDecisionManager接口 access 通道

注:加@comppent注解,把自定義類注冊(cè)成spring組件

將兩個(gè)supports()都設(shè)置成true

重寫decide()方法

@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {
? ? @Override
? ? public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
? ? ? ? //configattributes里存放著CustomFilterInvocationSecurityMetadataSource過濾出來的角色
? ? ? ? for (ConfigAttribute configAttribute : collection) {
? ? ? ? ? ? //如果你請(qǐng)求的url在數(shù)據(jù)庫中不具備角色
? ? ? ? ? ? if ("ROLE_def".equals(configAttribute.getAttribute())) {
? ? ? ? ? ? ? ? //在判斷是不是匿名用戶(也就是未登錄)
? ? ? ? ? ? ? ? if (authentication instanceof AnonymousAuthenticationToken) {
? ? ? ? ? ? ? ? ? ? System.out.println(">>>>>>>>>>>>>>>>匿名用戶>>>>>>>>>>>>>>");
? ? ? ? ? ? ? ? ? ? throw new AccessDeniedException("權(quán)限不足,無法訪問");
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? //這里面就是已經(jīng)登錄的其他類型用戶,直接放行
? ? ? ? ? ? ? ? ? ? System.out.println(">>>>>>>>>>>其他類型用戶>>>>>>>>>>>");
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //如果你訪問的路徑在數(shù)據(jù)庫中具有角色就會(huì)來到這里
? ? ? ? ? ? //Autherntication這里面存放著登錄后的用戶所有信息
? ? ? ? ? ? Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
? ? ? ? ? ? for (GrantedAuthority authority : authorities) {
? ? ? ? ? ? ? ? System.out.println(">>>>>>>authority(賬戶所擁有的權(quán)限):"+authority.getAuthority());
? ? ? ? ? ? ? ? System.out.println(">>>>>>>configAttribute(路徑需要的角色):"+configAttribute.getAttribute());
? ? ? ? ? ? ? ? //路徑需要的角色和賬戶所擁有的角色作比較
? ? ? ? ? ? ? ? if (authority.getAuthority().equals(configAttribute.getAttribute())) {
? ? ? ? ? ? ? ? ? ? System.out.println(">>>>>>>>>>>>>>>>>>進(jìn)來>>>>>>>>>>>>>>>>>");
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? @Override
? ? public boolean supports(ConfigAttribute configAttribute) {
? ? ? ? return true;
? ? }
? ? @Override
? ? public boolean supports(Class<?> aClass) {
? ? ? ? return true;
? ? }
}

創(chuàng)建WebSecurityConfig配置類

WebSecurityConfig實(shí)現(xiàn)WebSecurityConfigurerAdapter

注入一會(huì)所需要的類

SpringSecurity5.0之后必須密碼加密

將數(shù)據(jù)庫查出的賬戶密碼交給SpringSecurity去判斷

配置HttpSecurity

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
? ? @Autowired
? ? private UserService userService;
? ? @Autowired
? ? private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;
? ? @Autowired
? ? private CustomAccessDecisionManager customAccessDecisionManager;
? ? //springSecutity5.0之后必密碼加密
? ? @Bean
? ? PasswordEncoder passwordEncoder(){
? ? ? ? return new BCryptPasswordEncoder();
? ? }
? ? //將數(shù)據(jù)庫查出的賬戶密碼交給springsecurity去判斷
? ? @Override
? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception {
? ? ? ? auth.userDetailsService(userService);
? ? }
? ? //配置HttpSecurity
? ? @Override
? ? protected void configure(HttpSecurity http) throws Exception {
? ? ? ? http.authorizeRequests()
? ? ? ? ? ? ? ? .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public <O extends FilterSecurityInterceptor> O postProcess(O object){
? ? ? ? ? ? ? ? ? ? ? ? object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
? ? ? ? ? ? ? ? ? ? ? ? object.setAccessDecisionManager(customAccessDecisionManager);
? ? ? ? ? ? ? ? ? ? ? ? return object;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? .formLogin()
? ? ? ? ? ? ? ? .permitAll()
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? .csrf().disable();
? ? }
}

Controller 

@RestController
public class HelloController {
? ? @GetMapping("/hello")
? ? public String hello(){
? ? ? ? return "hello";
? ? }
? ? @GetMapping("/dba/hello")
? ? public String dba(){
? ? ? ? return "hello dba";
? ? }
? ? @GetMapping("/admin/hello")
? ? public String admin(){
? ? ? ? return "hello admin";
? ? }
? ? @GetMapping("/user/hello")
? ? public String user(){
? ? ? ? return "hello user";
? ? }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • java控制臺(tái)實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    java控制臺(tái)實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java控制臺(tái)實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java 學(xué)習(xí)筆記(入門篇)_java的基礎(chǔ)語法

    java 學(xué)習(xí)筆記(入門篇)_java的基礎(chǔ)語法

    從基礎(chǔ)語法開始,這個(gè)語法你也可以理解為英語或是漢語里面的語法,只不過大家各有各的特點(diǎn)和區(qū)別;那么在學(xué)習(xí)的過程中我們就要不斷的積累重要的類和方法,這樣寫程序就會(huì)方便快捷了,下面就開始學(xué)習(xí)java的基礎(chǔ)語法
    2013-01-01
  • nodejs與JAVA應(yīng)對(duì)高并發(fā)的對(duì)比方式

    nodejs與JAVA應(yīng)對(duì)高并發(fā)的對(duì)比方式

    這篇文章主要介紹了nodejs與JAVA應(yīng)對(duì)高并發(fā)的對(duì)比方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 詳解SpringBoot緩存的實(shí)例代碼(EhCache 2.x 篇)

    詳解SpringBoot緩存的實(shí)例代碼(EhCache 2.x 篇)

    這篇文章主要介紹了詳解SpringBoot緩存的實(shí)例代碼(EhCache 2.x 篇),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java復(fù)制(拷貝)數(shù)組的4種方法:arraycopy()方法、clone() 方法、copyOf()和copyOfRan

    Java復(fù)制(拷貝)數(shù)組的4種方法:arraycopy()方法、clone() 方法、copyOf()和copyOfRa

    這篇文章主要介紹了Java復(fù)制(拷貝)數(shù)組的4種方法:arraycopy()方法、clone() 方法、copyOf()和copyOfRan,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java中用數(shù)組實(shí)現(xiàn)環(huán)形隊(duì)列的示例代碼

    java中用數(shù)組實(shí)現(xiàn)環(huán)形隊(duì)列的示例代碼

    這篇文章主要介紹了java中用數(shù)組實(shí)現(xiàn)環(huán)形隊(duì)列的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • SpringBoot配置數(shù)據(jù)庫密碼加密的實(shí)現(xiàn)

    SpringBoot配置數(shù)據(jù)庫密碼加密的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot配置數(shù)據(jù)庫密碼加密的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • HelloSpringMVC注解版實(shí)現(xiàn)步驟解析

    HelloSpringMVC注解版實(shí)現(xiàn)步驟解析

    這篇文章主要介紹了HelloSpringMVC注解版實(shí)現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java?將Excel轉(zhuǎn)為UOS的操作方法

    Java?將Excel轉(zhuǎn)為UOS的操作方法

    以.uos為后綴的文件,表示Uniform?Office?Spreadsheet文件,是一種國產(chǎn)的辦公文件格式,該格式以統(tǒng)一辦公格式(UOF)創(chuàng)建,使用XML和壓縮保存電子表格,這篇文章主要介紹了Java?將Excel轉(zhuǎn)為UOS,需要的朋友可以參考下
    2022-09-09
  • 帶你了解10道java入門面試題

    帶你了解10道java入門面試題

    面試題相信大家都不陌生,想要一個(gè)好的工作面試題必不可少的,下面和小編一起來學(xué)習(xí)與了解Java當(dāng)中有有些什么面試題吧,希望能給你帶來幫助
    2021-08-08

最新評(píng)論