snailclimb / spring-security-jwt-guide Goto Github PK
View Code? Open in Web Editor NEW从零入门 !Spring Security With JWT(含权限验证)后端部分代码。
从零入门 !Spring Security With JWT(含权限验证)后端部分代码。
用postman测试一切正常,但是用axios访问就会有cors问题。
需要在CorsConfiguration
里允许OPTION请求:
.allowedMethods("GET", "POST", "DELETE", "PUT","OPTION")
建议直接实现SecurityContextRepository接口。
我看您的代码,第一次登录时是在controller层对于密码和用户名进行检查.但是在SpringSecurity中似乎是通过过滤器去验证UsernamePasswordToken成功之后才到达controller层执行之后的请求.这样的话SpringSecurity的作用似乎就体现不出来了
你这样配置了这个context-path为api,然后白名单里面又设置/api/auth/login放行,但是这个配置不会生效。
springsecurity默认匹配url的时候,不会携带项目名,也就是你的/api。
这里问题很大,我调试了很久才找到问题。不明白你测试的时候怎么会通过的,你登录的时候接口不会报错吗。
当重复注册时,并未按照设置的400报错,而是按照404。
没看到数据库表在哪里
最近在学习这个项目中的Spring Security,用其中的代码做了一个自己的项目,在线下用mvn package
和java -jar
都运行正常,使用DevOps部署到线上出现了循环依赖的异常。(为了使idea生成下面的图,加了几处@Autowired
注解)
要生成userController
,就需要通过自动装配方式使用userService
public class UserController {
private final UserService userService;
其中userService
需要bCryptPasswordEncoder
,也是通过@Autowired
方式装配
public class UserService {
@Autowired
private final BCryptPasswordEncoder bCryptPasswordEncoder;
bCryptPasswordEncoder
从securityConfig
中由注解@Bean
制造出
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
在此之前,securityConfig
需要得到userDetailsServiceImpl
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsServiceImpl;
userDetailsServiceImpl
又需要使用userService
来调用它的find
方法
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserService userService;
@Autowired
public UserDetailsServiceImpl(UserService userService) {
this.userService = userService;
}
@Override
public UserDetails loadUserByUsername(String name) {
User user = userService.find(name);
return new JwtUser(user);
}
}
但此时的userService
还没有制造好……于是有了循环依赖异常org.springframework.beans.factory.UnsatisfiedDependencyException
--> UnsatisfiedDependencyException
--> ... --> beans.factory.BeanCurrentlyInCreationException
通过改写loadUserByUsername
的方式,去除了UserDetailsServiceImpl
对UserService
的依赖,临时性地解决了这个异常。
jwt生成的token是可以通过绑定的加密算法Hmac直接校验的,为什么要把token存在redis去校验,这样子与其他方案生成加密串作为token有什么区别呢?
过滤器和配置均搭配好,postman无论是post还是get,请求后没有任何响应,把SecurityConfig.configure(HttpSecurity http)中的代码注释掉 获取用户接口可以使用,但是注册就报403权限了
h2数据库页面访问地址 http://{host}:9333/h2-console/ 请修改为http://{host}:9333/api/h2-console/
是"README.md"没更新吧,正确的注册地址是"/api/users/sign-up"
而且加了"/api"根路径配置,所以正确登录地址应该是"/api/auth/login"
后台肯定是希望用户登录一段时间没操作后失效了,如果有操作要续期,如果使用jwt的过期时间每次续期都要重新生成,如果用redis管理过期时间,那jwt就没有什么意义了
项目中不存在UsernamePasswordAuthenticationFilter这个过滤器
从这3方面讲一讲,认证服务器、资源服务器、客户端。
最好再来一个 SpringBoot 1.x 和 SpringBoot 2.x 的版本!
请问SecurityConstants类中JWT_SECRET_KEY 是如何生成的
错误:
at github.javaguide.springsecurityjwtguide.security.filter.JWTAuthenticationFilter.successfulAuthentication(JWTAuthenticationFilter.java:73) ~[classes/:na]
http 响应
{ "timestamp": "2019-10-14T01:23:26.399+0000", "status": 500, "error": "Internal Server Error", "message": "No message available", "path": "/auth/login" }
public void updateFrom(UserUpdateRequest userUpdateRequest) {
if (Objects.nonNull(userUpdateRequest.getFullName())) {
this.setFullName(userUpdateRequest.getFullName());
}
if (Objects.nonNull(userUpdateRequest.getPassword())) {
this.setPassword(userUpdateRequest.getPassword());
}
if (Objects.nonNull(userUpdateRequest.getEnabled())) {
this.setEnabled(userUpdateRequest.getEnabled());
}
}
版本号 1796044
为什么User类中要用SimpleGrantedAuthority这个类再包一层
和注册使用的数据类型一样 也是 raw 吗?
我看了代码 都是使用的构造方式注入,为什么不用@resource或者@Autowired 注解式注入呢? 是有什么说法吗?
String token = JwtTokenUtils.createToken(jwtUser.getUsername(), roles, rememberMe.get());
SpringSecurity介绍.md文件中给出的配置类SecurityConfig和项目代码中的SecurityConfig内容不一样啊。
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsServiceImpl;
/**
* 密码编码器
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService createUserDetailsService() {
return userDetailsServiceImpl;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 设置自定义的userDetailsService以及密码编码器
auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
// 禁用 CSRF
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/auth/login").permitAll()
// 指定路径下的资源需要验证了的用户才能访问
.antMatchers("/api/**").authenticated()
.antMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN")
// 其他都放行了
.anyRequest().permitAll()
.and()
//添加自定义Filter
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// 不需要session(不创建会话)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 授权异常处理
.exceptionHandling().authenticationEntryPoint(new JWTAuthenticationEntryPoint())
.accessDeniedHandler(new JWTAccessDeniedHandler());
}
}
/**
* @author shuang.kou Saving
* @version 1.1
* @date 2020.11.28 14:16
* @description Spring Security配置类
**/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final StringRedisTemplate stringRedisTemplate;
public SecurityConfiguration(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
/**
* 密码编码器
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors(withDefaults())
// 禁用 CSRF
.csrf().disable()
.authorizeRequests()
// 指定的接口直接放行
// swagger
.antMatchers(SecurityConstants.SWAGGER_WHITELIST).permitAll()
.antMatchers(SecurityConstants.H2_CONSOLE).permitAll()
.antMatchers(HttpMethod.POST, SecurityConstants.SYSTEM_WHITELIST).permitAll()
// 其他的接口都需要认证后才能请求
.anyRequest().authenticated()
.and()
//添加自定义Filter
.addFilter(new JwtAuthorizationFilter(authenticationManager(), stringRedisTemplate))
// 不需要session(不创建会话)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 授权异常处理
.exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint())
.accessDeniedHandler(new JwtAccessDeniedHandler());
// 防止H2 web 页面的Frame 被拦截
http.headers().frameOptions().disable();
}
/**
* Cors配置优化
**/
@Bean
CorsConfigurationSource corsConfigurationSource() {
org.springframework.web.cors.CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(singletonList("*"));
// configuration.setAllowedOriginPatterns(singletonList("*"));
configuration.setAllowedHeaders(singletonList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "PUT", "OPTIONS"));
configuration.setExposedHeaders(singletonList(SecurityConstants.TOKEN_HEADER));
configuration.setAllowCredentials(false);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
// DaoAuthenticationProvider
return source;
}
}
为什么登录是localhost:9333/api/auth/login而不是localhost:9333/auth/login?
在SecurityConfig 中的代码是这样的
.antMatchers(HttpMethod.POST, "/auth/login").permitAll()
// 指定路径下的资源需要验证了的用户才能访问
.antMatchers("/api/**").authenticated()
为什么前面还需要加/api?求解惑。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.