spring安全不识别角色-预授权或休眠问题?

bis0qfac  于 2021-07-08  发布在  Java
关注(0)|答案(0)|浏览(194)

我正在尝试使用spring/angular堆栈进入Spring Security ,并找到了bezcoder的一些代码,可以在这里查找
https://github.com/bezkoder/angular-10-jwt-authentication 以及https://github.com/bezkoder/spring-boot-spring-security-jwt-authentication
登录和注册工作,但是,我有麻烦的授权为某些接入点。例如,我不能输入urllocalhost:8080/api/test/user -如果我试着error:unauthorized"
我想我把问题缩小到了通过@preauthorize注解处理角色。在下面的“testcontroller”中,在公共字符串allaccess()函数上设置的@preauthorize(“permitall()”)可以工作,但是带有@preauthorize的引用特定角色的所有其他函数都不能工作。控制器:

package com.savetravel.SaveTravel.Controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.savetravel.SaveTravel.Repositories.UserRepository;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/test")
public class TestController {

    @Autowired
    UserRepository userRepositoy;

    @PreAuthorize("permitAll()")
    @GetMapping("/all")
    public String allAccess() {
        return "Public Content.";
    }

    @GetMapping("/user")
    @PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
    public String userAccess() {
        return "User Content.";
    }

    @GetMapping("/mod")
    @PreAuthorize("hasRole('MODERATOR') or hasRole('ADMIN')")
    public String moderatorAccess() {
        return "Moderator Board.";
    }

    @GetMapping("/admin")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String adminAccess() {
        return "Admin Board.";
    }

}

还有我的网络安全配置

package com.savetravel.SaveTravel;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.savetravel.SaveTravel.Security.Services.UserDetailsServiceImpl;
import com.savetravel.SaveTravel.Security.jwt.AuthEntryPointJwt;
import com.savetravel.SaveTravel.Security.jwt.AuthTokenFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        proxyTargetClass = true,
        prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Autowired
    public AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

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

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests().antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/test/**").permitAll()
            .anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}

如果我从控制器中的函数中删除角色的@preauthorize注解,一切正常(返回到websecurityconfig,这不是它的本意),我很困惑,删除@preauthorize注解并更改websecurityconfig中的configure()函数with.authorizerequests().antmatchers(“/api/test/user”).hasrole(“user”)不会产生任何效果,例如:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests()
            .antMatchers("/api/test/user").hasRole("USER")
            .antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/test/**").permitAll()
            .anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

似乎后端根本不考虑角色。我唯一改变的是我使用hibernateh2而不是mysql,因为它是在原始代码中使用的。因此,我的application.properties看起来是这样的(原始配置被注解掉了):

spring.datasource.url=jdbc:h2:mem:savetravel;DATABASE_TO_UPPER=false
spring.h2.console.enabled=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.jpa.hibernate.hbm2ddl.auto=create
spring.datasource.username=myusername
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.platform=h2
spring.datasource.initialize=true

# Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/?user=root&password=rootpassword");

# PreparedStatement ps = connection.prepareStatement("CREATE DATABASE databasename");

# int result = ps.executeUpdate();

# spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect

# spring.jpa.hibernate.ddl-auto= update

# SQL GENERATE CONFIGURATION

# datasource.schema=  the schema sql script to load. By default it is schema-${platform}.sql then schema.sql;

# datasource.data= the data sql script. By default, it is data-${platform}.sql then data.sql;

# spring.h2.console.enabled=true

# spring.jpa.hibernate.ddl-auto=none

app.jwt.header=Authorization
app.jwtSecret= loginSecretKey
app.jwtExpirationMs= 86400000

使用data.sql:

INSERT INTO roles(name) VALUES('ROLE_USER');
INSERT INTO roles(name) VALUES('ROLE_MODERATOR');
INSERT INTO roles(name) VALUES('ROLE_ADMIN');

INSERT INTO users(id, username, email, password) VALUES(777, 'testuser', 'testuser@test.de', '$2a$10$tmPQGqC7XxNmFKwfufGybOxb7HIDA.0lEOtb3ejAiiBn4EfoxI9TK');
INSERT INTO user_roles(user_id, role_id) VALUES(777, 1);
INSERT INTO user_roles(user_id, role_id) VALUES(777, 2);

但我无法想象h2是个问题,因为以下测试不会失败:

@Test
    public void simpleConstructorTestUser() {
        User testUser = new User("testUser", "test@test.de", "testpassword");
        assertNotNull(testUser.getUsername());

    }

    @Test
    @PostMapping("/user")
    public void userAccess() {

        String userName = testUser.getUsername();
        System.out.println(userName);
        Optional<User> userFromDB = userRepository.findByUsername(userName);
        Set<Role> roles = userFromDB.get().getRoles();

        for (Role role : roles) {
            String roleType = role.getName().name();
            assertArrayEquals(roleType, "ROLE_USER");
        }
    }

但也许我错了,它必须与h2而不是mysql有关?为了全面起见:我的pom.xml是:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.savetravel</groupId>
    <artifactId>SaveTravel</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SaveTravel</name>
    <description>TravelApp</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </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>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.3</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

很多问题,令人尴尬的是:我真的不知道在哪里搜索来解决这个问题,特别是因为代码应该是可以工作的,而且我的一个同事似乎能够在没有更改的情况下运行它。如果有人能告诉我从哪里开始我的旅程,我会很高兴,因为我认为spring安全应用程序很棒,我很想更好地了解安全程序。所以如果有人有想法,比如:
我可以在spring或angular中编写测试来检查某些东西
我可以查看的配置(我使用linux,也许这是个问题?)
别的。。。提前谢谢!汤姆

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题