来分享一下“mall整合SpringSecurity及JWT实现认证授权实战”的完整攻略。
1. 环境准备
要完成该攻略,首先需要准备好以下环境:
- JDK 1.8+
- Maven 3.x
- IntelliJ IDEA 2019.2+(或其他任意IDE)
2. 创建maven项目
使用maven创建一个空白的Spring Boot项目,并引入必要的依赖,包括Spring Boot、Spring Security和JWT等。
3. 配置Spring Security
创建一个继承WebSecurityConfigurerAdapter
的配置类,重写configure()
方法以进行身份验证和授权设置。其中包括:
- 配置用户身份验证方式:可以通过数据库、自定义验证等方式进行用户验证。
- 配置权限验证:可以通过
@PreAuthorize
或@PostAuthorize
注解进行方法级别的授权。
示例:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许公开访问的url
.anyRequest().authenticated() // 其余的URL需要身份验证
.and()
.formLogin()
.loginPage("/login") // 登录页面URL
.loginProcessingUrl("/doLogin") // 登录接口URL
.usernameParameter("username") // 登录用户名参数
.passwordParameter("password") // 登录密码参数
.successHandler(new MyAuthenticationSuccessHandler()) // 登录成功的处理器
.failureHandler(new MyAuthenticationFailureHandler()) // 登录失败的处理器
.permitAll()
.and()
.logout()
.logoutUrl("/logout") // 退出登录的接口URL
.logoutSuccessUrl("/login") // 退出成功后跳转的URL
.permitAll();
http.csrf().disable(); // 禁用CSRF保护
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
注:上述示例中,我们使用了BCryptPasswordEncoder
加密方式对用户密码进行加密。
4. 配置JWT
在pom.xml
文件中添加以下依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
接着,我们需要创建一个JWT工具类,实现JWT的生成和解析等功能。
示例:
@Component
public class JwtUtils {
/**
* 过期时间,单位:分钟
*/
private static final long EXPIRATION = 30;
/**
* 秘钥
*/
private static final String SECRET_KEY = "mall";
/**
* 创建JWT Token
*
* @param subject 用户信息
* @return JWT Token
*/
public String createToken(String subject) {
Date now = new Date();
Date expirationDate = new Date(now.getTime() + EXPIRATION * 60 * 1000);
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
/**
* 解析JWT Token,并返回其中的subject(用户信息)
*
* @param token JWT Token
* @return 用户信息
*/
public String parseToken(String token) {
try {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
} catch (Exception e) {
return null;
}
}
}
5. 添加JWT认证
为了使用JWT进行身份验证,我们需要修改WebSecurityConfig
类以支持JWT。
示例:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtils jwtUtils;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许公开访问的url
.anyRequest().authenticated() // 其余的URL需要身份验证
.and()
.formLogin()
.loginPage("/login") // 登录页面URL
.loginProcessingUrl("/doLogin") // 登录接口URL
.usernameParameter("username") // 登录用户名参数
.passwordParameter("password") // 登录密码参数
.successHandler(new MyAuthenticationSuccessHandler()) // 登录成功的处理器
.failureHandler(new MyAuthenticationFailureHandler()) // 登录失败的处理器
.permitAll()
.and()
.logout()
.logoutUrl("/logout") // 退出登录的接口URL
.logoutSuccessUrl("/login") // 退出成功后跳转的URL
.permitAll();
http.csrf().disable(); // 禁用CSRF保护
// 添加JWT认证
http.addFilterBefore(new JwtAuthenticationFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
然后,我们需要创建一个JwtAuthenticationFilter
,用于验证JWT,并将用户信息添加到spring security的上下文中。
示例:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private JwtUtils jwtUtils;
public JwtAuthenticationFilter(JwtUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.startsWith("Bearer ")) {
String jwt = authorization.substring(7);
String subject = jwtUtils.parseToken(jwt);
if (subject != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(subject);
if (jwtUtils.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
}
filterChain.doFilter(request, response);
}
}
6. 测试
现在我们可以进行测试了。我们可以编写一个测试接口,例如/api/test
,来测试JWT认证是否生效。
示例:
@RestController
@RequestMapping("/api")
public class TestController {
@GetMapping("/test")
@PreAuthorize("hasRole('ADMIN')")
public String test() {
return "Hello, World!";
}
}
其中,@PreAuthorize("hasRole('ADMIN')")
表示只有具有ADMIN
角色的用户才能访问该接口。
接下来,我们可以在Postman或其他工具中发送请求进行测试。请求头中需要携带如下信息:
Authorization:Bearer {JWT Token}
其中,JWT Token可以通过JwtUtils
工具类生成。
如果授权成功,接口将返回“Hello, World!”消息。
这就是使用Spring Security和JWT实现认证授权的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:mall整合SpringSecurity及JWT实现认证授权实战 - Python技术站