Springboot Security 有关postman访问401的问题

主要问题是csrf的问题,这个是防止跨站请求伪造攻击的,目前高版本securitys是默认开启的,需要关闭。

在设置类里添加

http.csrf().disable()

还有一个困扰我4-5个小时的问题,因为我是刚学springboot,没有想到SecurityConfiguration是要在主运行文件也就是xxxxxxApplication一个包内的,不然就上边那行代码就会失效。

有这个问题的只需要把SecurityConfiguration类放到和xxxxxxApplication一个包内就可以了。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面介绍一下如何使用Spring Boot、Spring Security和JWT实现登录、认证和鉴权。 1. 添加依赖 在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 2. 配置Spring Security 在 `application.yml` 文件中配置 Spring Security: ```yaml spring: security: user: name: admin password: admin ``` 这里定义了一个用户名为 admin,密码为 admin 的用户。 3. 实现Controller 实现一个简单的Controller,用于演示登录、认证和鉴权: ```java @RestController public class HelloWorldController { @GetMapping("/hello") public String hello() { return "Hello World"; } @GetMapping("/admin") public String admin() { return "Hello Admin"; } } ``` 其中,`/hello` 是一个公共的接口,不需要鉴权;`/admin` 是需要鉴权的接口,只有管理员才能访问。 4. 实现认证和鉴权逻辑 在 `SecurityConfig` 类中,实现认证和鉴权逻辑: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/hello").permitAll() .antMatchers("/admin").hasRole("ADMIN") .and() .apply(new JwtConfigurer(jwtTokenProvider)); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } } ``` 其中,`JwtTokenProvider` 是一个自定义的类,用于生成和验证 JWT。 5. 实现JWT逻辑 在 `JwtTokenProvider` 类中,实现JWT逻辑: ```java @Component public class JwtTokenProvider { private static final String SECRET_KEY = "mySecretKey"; private static final long EXPIRATION_TIME = 864_000_000; // 10 days public String createToken(String username, List<String> roles) { Claims claims = Jwts.claims().setSubject(username); claims.put("roles", roles); Date now = new Date(); Date expiration = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(expiration) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { throw new JwtAuthenticationException("JWT token is invalid or expired", e); } } public Authentication getAuthentication(String token) { UserDetails userDetails = User.builder() .username(getUsername(token)) .password("") .authorities(getRoles(token).stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList())) .build(); return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); } private String getUsername(String token) { return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject(); } private List<String> getRoles(String token) { return (List<String>) Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().get("roles"); } } ``` 6. 实现认证逻辑 在 `UserDetailsServiceImpl` 类中,实现认证逻辑: ```java @Service public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (username.equals("admin")) { return User.builder() .username("admin") .password("$2a$12$EIlCPMzjwB2s2sG1c8yvIuVpT0X1OgW3T8ZvTJjqc5wU1bh6q3K6C") .roles("ADMIN") .build(); } else { throw new UsernameNotFoundException("User not found"); } } } ``` 这里返回一个用户名为 admin,密码为 admin(经过 BCrypt 加密)的用户。 7. 实现JWT过滤器 在 `JwtTokenFilter` 类中,实现JWT过滤器: ```java public class JwtTokenFilter extends OncePerRequestFilter { @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { String token = getToken(httpServletRequest); if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(auth); } filterChain.doFilter(httpServletRequest, httpServletResponse); } private String getToken(HttpServletRequest request) { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { return authHeader.substring(7); } return null; } } ``` 8. 实现JWT配置类 最后,在 `JwtConfigurer` 类中,实现JWT配置类: ```java public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { private JwtTokenProvider jwtTokenProvider; public JwtConfigurer(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void configure(HttpSecurity http) { JwtTokenFilter customFilter = new JwtTokenFilter(); http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); } } ``` 9. 测试 使用 Postman 分别测试 `/hello` 和 `/admin` 接口,可以发现: - 访问 `/hello` 接口时,不需要鉴权,返回结果为 `Hello World`; - 访问 `/admin` 接口时,需要鉴权,如果使用正确的用户名和密码(admin/admin),返回结果为 `Hello Admin`;否则,返回 401 Unauthorized 错误。 至此,登录、认证和鉴权的实现就完成了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值