下面是“Spring Boot整合Shiro+JWT实现前后端分离”的完整攻略,包含以下步骤:
1. 添加依赖
首先要在项目的pom.xml文件中添加相关依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2. 添加配置文件
在项目的application.yml配置文件中添加相应的配置。
# Shiro配置
shiro:
filter:
anon: /login, /api/doc, /static/**
authc: /**
jwt:
secret: secret
issuer: iss
expiration: 1800
3. 编写Realm
编写自定义Realm类,并继承org.apache.shiro.realm.AuthorizingRealm类。
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
User user = userService.findByUsername(username);
if (user == null) {
throw new UnknownAccountException();
}
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
}
}
4. 配置ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/api/doc", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/**", "jwt");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
5. 配置ShiroSecurityManager
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
securityManager.setSubjectFactory(servletContainerSubjectFactory());
return securityManager;
}
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return userRealm;
}
@Bean
public ServletContainerSubjectFactory servletContainerSubjectFactory() {
return new ServletContainerSubjectFactory();
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("SHA-256");
hashedCredentialsMatcher.setHashIterations(1024);
return hashedCredentialsMatcher;
}
6. 编写登录接口(示例1)
@PostMapping("/login")
public Result login(String username, String password) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
SecurityUtils.getSubject().login(token);
} catch (UnknownAccountException e) {
return Result.error("用户名不存在");
} catch (IncorrectCredentialsException e) {
return Result.error("密码不正确");
} catch (AuthenticationException e) {
return Result.error("登录失败");
}
String jwt = JwtUtils.createJwt(username);
Map<String, Object> data = new HashMap<>();
data.put("token", jwt);
return Result.ok("登录成功", data);
}
7. 编写JWT过滤器(示例2)
public class JwtFilter extends AuthenticatingFilter {
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
String jwt = JwtUtils.getJwtFromRequest((HttpServletRequest) request);
return new JwtToken(jwt);
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String jwt = JwtUtils.getJwtFromRequest(req);
if (jwt == null) {
resp.setStatus(401);
return false;
}
try {
getSubject(request, response).login(new JwtToken(jwt));
} catch (UnknownAccountException e) {
resp.setStatus(401);
return false;
}
return true;
}
}
完成以上步骤后,就可以通过前后端分离的方式,使用Shiro和JWT保护你的API了。
以上是Spring Boot整合Shiro+JWT实现前后端分离的完整攻略,其中包含两个示例:
- 编写登录接口
- 编写JWT过滤器
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring boot整合shiro+jwt实现前后端分离 - Python技术站