programing

Spring Security()의 역할이 작동하지 않습니다.

javajsp 2023. 9. 21. 20:07

Spring Security()의 역할이 작동하지 않습니다.

Spring Security & Thymeleaf를 사용할 때, 특히 hasRole 표현식을 사용하려고 할 때 문제가 발생했습니다.'ADMIN' 사용자에게 'ADMIN' 역할이 있지만hasRole('ADMIN')요 거짓으로 됩니다.

내 html:

1.<div sec:authentication="name"></div> <!-- works fine -->
2.<div sec:authentication="principal.authorities"></div> <!-- works fine -->

3.<div  sec:authorize="isAuthenticated()" >true</div> <!-- works fine -->
4.<span th:text="${#authorization.expression('isAuthenticated()')}"></span> <!-- works fine -->

5.<div th:text="${#vars.role_admin}"></div> <!--Works fine -->
6.<div  sec:authorize="${hasRole('ADMIN')}" > IS ADMIN </div> <!-- Doesnt work -->
7.<div  sec:authorize="${hasRole(#vars.role_admin)}" > IS ADMIN </div> <!-- Doesnt work -->
8.<div th:text="${#authorization.expression('hasRole(''ADMIN'')')} "></div> <!-- Doesnt work -->
9.<div th:text="${#authorization.expression('hasRole(#vars.role_admin)')}"></div> <!-- Doesnt work -->

결과:

1.admin
2.[ADMIN]
3.true
4.true
5.ADMIN
6."prints nothing because hasRole('ADMIN') resolves to false"
7."prints nothing because hasRole(#vars.role_admin) resolves to false"
8.false
9.false

security.xml 파일에서 use-expression을 활성화했습니다.

<security:http auto-config="true" use-expressions="true">

또한 Spring SecurityDialect를 내 구성에 포함시켰습니다.

<bean id="templateEngine"
      class="org.thymeleaf.spring4.SpringTemplateEngine">
    <property name="templateResolver" ref="templateResolver" />  
    <property name="additionalDialects">
        <set>
            <bean class="org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect" />
        </set>
    </property>      
</bean>

내 pom.xml 파일에 있는 모든 필요한 종속성

<!--Spring security--> 
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>4.0.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.0.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>4.0.1.RELEASE</version>
    </dependency>        
    
    <!--Thymeleaf Spring Security-->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>2.1.2.RELEASE</version>
        <scope>compile</scope>
    </dependency>

역할.자바

@Entity
@Table(name = "roles")

    public class Role implements Serializable {
    
        @Id
        @Enumerated(EnumType.STRING)
        private RoleType name;
        //... getters, setters
    }

역할 유형

public enum RoleType {

    ADMIN 
}

그리고.User의 집합을 갖습니다.Roles

요?hasRole()을 안하나요요?

당신의 도움에 감사드립니다, 감사합니다.

해결방법

th:if="${#strings.contains(#authentication.principal.authorities,'ADMIN')}"

사용해보기hasAuthorityhasRoleHTML 태그 안에 있습니다.

sec:authorize="hasAuthority('ADMIN')"

개념이 없습니다.

  • 사용하는 경우hasRole('ADMIN')의 , , 에서의ADMIN Enum다여야 .ROLE_ADMINADMIN.
  • 사용하는 경우hasAuthority('ADMIN'),당신의.ADMIN Enum다여야 .ADMIN.

hasRole().hasAuthority(),그렇지만hasRole()hAuthority 없이ROLE_접두사를 붙입니다

허용된 답변은 이 게시물에서 찾을 수 있습니다: 역할과 부여된 역할의 차이춘계의 권위

하는 것과 Spring Security 3.x 에서 4.x 로를 변경하는 것입니다. 로hasRole().hasAuthority()나를 위해 속임수를 썼답니다.

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/ #e-common-built-in

사용자 역할을 확인하기 위해 필요한 부분에서 유사한 작업을 수행해야 했습니다.나는 아래에서 했습니다.

<div th:if="${ #authorization.expression('isAuthenticated()') and #strings.contains(#authentication.principal.authorities,'ADMIN')}">          
    <a th:href="@{/somelink}">ADMIN LINK</a>
 </div>

누군가에게 도움이 되길 바랍니다.

저도 최근에 똑같은 문제가 생겼습니다.당신이 해야 할 일은 다음과 같습니다.

  1. html에 다음 문장을 추가합니다.

    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"   xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
    

(사용하는 항목에 따라 spring security4 또는 spring security3 중에서 변경할 수 있습니다.)

  1. 라이브러리에 이 리소스를 추가했는지 확인합니다.그래들을 사용하고 있지만 메이븐도 마찬가지입니다.

    compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE'
    
  2. SpringWebConfiguration 클래스 또는 xml에서 thymeleaf SpringSecurity에 대한 방언을 추가해야 합니다.구성에 자바 클래스를 사용하고 있습니다.

    @Bean
    public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine templateEngine = new SpringTemplateEngine();
    templateEngine.setTemplateResolver(templateResolver());
    templateEngine.addDialect(new SpringSecurityDialect());
    return templateEngine;
    }
    

하지만 알렉스 소스가 말하는 대로 정의할 수도 있습니다: 스프링 보안과 Thymleaf는 작동하지 않습니다.

이 방법이 당신에게 효과가 있기를 바랍니다!반가워요!

저도 같은 문제에 휘말리게 되었는데, 그것은 바로 그 문제 때문입니다.spring-security 4.0인지.thymeleaf-extras-springsecurity4다와(와) 호환되지 .spring-security 및 4.0thymeleaf 2.x. 그래서 다운그레이드를 했습니다.spring-security전.3.2.9.RELEASE그리고 작동하기 시작했습니다. 기능을 사용하려는 4.0, 그럼 당신이 들어올리는 것을 시도해 볼 수 있을 것입니다.thymeleaf-extras-springsecurity4.3.0.0.RELEASE그리고.thymeleaf증에 대한 3.0

은 입니다.spring-security또는 스프링 부트 버전을 1.4.x(아직 베타 버전)로 업그레이드합니다.

당신의 구체적인 시나리오에서 아래 폼을 변경하면 역할이 작동합니다.

<!--Spring security--> 
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>3.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>3.2.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>3.2.9.RELEASE</version>
    </dependency>        

    <!--Thymeleaf Spring Security-->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>2.1.2.RELEASE</version>
        <scope>compile</scope>
    </dependency>

공식 문서를 참조합니다.http://www.thymeleaf.org/doc/articles/springsecurity.html

<div sec:authorize="hasRole('ROLE_ADMIN')">
  This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
  This content is only shown to users.
</div>

당신은 아래와 같이 시도해 볼 수 있습니까?${...}.

<div sec:authorize="hasRole('ADMIN')">IS ADMIN</div>

저는 당신이 다음과 같은 역할의 접두사를 붙이지 않았다고 생각합니다.ROLE_. 그렇다면 아래와 같이 접두사도 추가해야 합니다.

<div sec:authorize="hasRole('ROLE_ADMIN')">IS ADMIN</div>

몇 주간의 시행착오 끝에, 이것은 저에게 효과가 있었습니다.

https://mvnrepository.com/ 에 따라 최신 버전으로 업그레이드하기

스프링 부츠 스타터 타임리프 엑스트라 스프링 시큐리티 5 봄 부츠용 타임리프

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        <version>2.3.0.RELEASE</version>
    </dependency>

어떤 버전의 종속성이 다른 버전과 잘 작동하는지는 정말 모르지만, 현재(2020년 5월 19일)는 저에게 효과가 있었습니다.

누군가에게 도움이 되길 바랍니다.

Spring boot 2에서는 has Role() 또는 has Authority()를 사용할 수 있습니다.다른 점이 있다면 ROLE_을 사용하여 has Austhority() 메서드가 있습니다.그래서 ROLE_ADMIN의 경우,

 @PreAuthorize("hasRole('ADMIN')") == @PreAuthorize("hasAuthority('ROLE_ADMIN')")

저도 비슷한 문제가 있어서 이 문제를 해결했습니다.

다음 엔티티를 사용합니다.

사용자 엔터티


    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Entity
    public class User implements UserDetails, CredentialsContainer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false,unique = true)
        private String username;
    
        @Column(nullable = false,unique = true)
        private String email;
    
        private String password;
    
        @Builder.Default
        private Boolean accountNonExpired = true;
    
        @Builder.Default
        private Boolean accountNonLocked = true;
    
        @Builder.Default
        private Boolean credentialsNonExpired = true;
    
        @Builder.Default
        private Boolean enabled = true;
    
        @CreationTimestamp
        @Column(updatable = false)
        private Timestamp createdDate;
    
        @UpdateTimestamp
        private Timestamp lastModifiedDate;
    
        @Singular
        @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
        @JoinTable(
                name = "user_role",
                joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
        )
        private Set<Role> roles = new HashSet<>();
    
        @Override
        public void eraseCredentials() {
            this.password = null;
        }
    
        @Override
        @Transient
        public Collection<? extends GrantedAuthority> getAuthorities() {
            Set<SimpleGrantedAuthority> authorities =
                    this.roles.stream().
                    map(Role::getAuthorities).
                    flatMap(Set::stream).
                    map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
                    collect(Collectors.toSet());
    
            roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
            return authorities;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return accountNonExpired;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return accountNonLocked;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return credentialsNonExpired;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    }

역할 실체

    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Entity
    public class Role  {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private String name;
    
        @ManyToMany(mappedBy = "roles")
        private Set<User> users;
    
        @Singular
        @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
        @JoinTable(
                name = "role_authority",
                joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
                inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")
        )
        private Set<Authority> authorities = new HashSet<>();
    
    
    }

권위 있는 실체


    @Setter
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @Entity
    public class Authority  {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        Long id;
    
        private String permission;
    
        @Singular
        @ManyToMany(mappedBy = "authorities")
        private Set<Role> roles = new HashSet<>();
    
    
    }

부츠트랩

        var storeItemCreate = authorityRepository.save(Authority.builder().permission("store.item.create").build());
        var storeItemRead = authorityRepository.save(Authority.builder().permission("store.item.read").build());
        var storeItemUpdate = authorityRepository.save(Authority.builder().permission("store.item.update").build());
        var storeItemDelete = authorityRepository.save(Authority.builder().permission("store.item.delete").build());



        var admin = roleRepository.save(Role.builder().
                authority(storeItemCreate).
                authority(storeItemRead).
                authority(storeItemUpdate).
                authority(storeItemDelete).
                name("ROLE_ADMIN").build());

        var customer = roleRepository.save(Role.builder().
            authority(storeItemRead).
            name("ROLE_CUSTOMER").
            build());

        userRepository.save(User.builder().
                role(admin).
                username("admin").
                password(passwordEncoder.encode("admin")).
                email("admin@admin.com").
                build()
        );


        userRepository.save(User.builder().
                role(customer).
                username("user").
                password(passwordEncoder.encode("user")).
                email("user@user.com").
                build()
        );

내가 일하는 이유가 Authority()와 hasRole()이 사용자 엔티티 inget의 조각입니다.관청방식

        Set<SimpleGrantedAuthority> authorities =
                this.roles.stream().
                map(Role::getAuthorities).
                flatMap(Set::stream).
                map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
                collect(Collectors.toSet());

        roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
        return authorities;

ROLE_NAMEOFROLE spring이라는 이름의 권한이 있을 때는 권한처럼 취급합니다. 접두사가 존재하지 않을 때는 권한처럼 취급합니다.

권한도 가지고 있어야 합니다. "ROLE_ADMIN"

그게 올바른 접근법인지 잘 모르겠어요!!!

@구성 요소 공용 클래스 LoginSuccessHandler가 SavedRequestAware를 확장합니다.인증성공 처리기 {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws ServletException, IOException {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();

        String redirectURL = request.getContextPath();
        if (userDetails.hasRole("ROLE_ADMIN")) {
            redirectURL = "admin-dashboard";
        } else if (userDetails.hasRole("ROLE_EMPLOYEE")) {
            redirectURL = "dashboard";
        } else if (userDetails.hasRole("ROLE_TRAINEE")) {
            redirectURL = "dashboard";
        }
        response.sendRedirect(redirectURL);
    }

}

저 같은 경우에는.hasRole특정 컨트롤러의 엔드포인트에는 작동하지 않는 반면 다른 컨트롤러 엔드포인트에는 작동합니다.

저는 이 컨트롤러가@RequestMapping끝나고@RestController.

@RestController
@RequestMapping("/test/v1")
public class TestController {
}

제가 주문을 바꿔서.hasRole현재 작동 중:

@RequestMapping("/test/v1")
@RestController
public class TestController {
}

언급URL : https://stackoverflow.com/questions/30788105/spring-security-hasrole-not-working