我正在尝试使用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,也许这是个问题?)
别的。。。提前谢谢!汤姆
暂无答案!
目前还没有任何答案,快来回答吧!