您好,登录后才能下订单哦!
在现代Web开发中,快速搭建一个高效、安全的后端服务是每个开发者的追求。Spring Boot作为Java生态中最流行的框架之一,以其简洁的配置和强大的功能赢得了广泛的青睐。结合JWT(JSON Web Token)、Shiro(Apache Shiro)和MybatisPlus,我们可以快速构建一个功能完善的后端脚手架。本文将详细介绍如何使用这些技术栈实现一个Restful风格的后端服务。
首先,我们需要创建一个Spring Boot项目。可以使用Spring Initializr来快速生成项目骨架。选择以下依赖:
生成项目后,导入到IDE中,确保项目结构如下:
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── demo
│ │ ├── config
│ │ ├── controller
│ │ ├── entity
│ │ ├── mapper
│ │ ├── service
│ │ └── DemoApplication.java
│ └── resources
│ ├── application.yml
│ └── mapper
└── test
└── java
└── com
└── example
└── demo
MybatisPlus是Mybatis的增强工具,提供了许多便捷的功能。首先,我们需要在application.yml
中配置数据库连接和MybatisPlus的相关设置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
接下来,创建一个实体类User
:
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
private String role;
}
然后,创建Mapper接口UserMapper
:
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
Shiro是一个强大的安全框架,而JWT是一种轻量级的身份验证机制。我们将结合两者来实现用户认证和授权。
首先,添加Shiro和JWT的依赖:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
接下来,创建一个JWT工具类JwtUtil
:
public class JwtUtil {
private static final String SECRET_KEY = "your-secret-key";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1天
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
然后,配置Shiro的Realm
和Filter
:
public class JwtRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole(user.getRole());
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String jwtToken = (String) token.getPrincipal();
String username = JwtUtil.getUsernameFromToken(jwtToken);
if (username == null) {
throw new AuthenticationException("Invalid token");
}
User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
if (user == null) {
throw new AuthenticationException("User not found");
}
return new SimpleAuthenticationInfo(username, jwtToken, getName());
}
}
public class JwtFilter extends AuthenticatingFilter {
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String token = httpRequest.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
return null;
}
return new JwtToken(token.substring(7));
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
AuthenticationToken token = createToken(request, response);
if (token == null) {
return true;
}
try {
getSubject(request, response).login(token);
return true;
} catch (Exception e) {
return false;
}
}
}
最后,配置Shiro的SecurityManager
和Filter
:
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
Map<String, Filter> filters = new HashMap<>();
filters.put("jwt", new JwtFilter());
factoryBean.setFilters(filters);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/**", "jwt");
factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return factoryBean;
}
@Bean
public SecurityManager securityManager(JwtRealm jwtRealm) {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(jwtRealm);
return securityManager;
}
@Bean
public JwtRealm jwtRealm() {
return new JwtRealm();
}
}
现在,我们可以实现一些Restful API来测试我们的脚手架。首先,创建一个UserController
:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
if (user != null && user.getPassword().equals(password)) {
return JwtUtil.generateToken(username);
}
throw new RuntimeException("Invalid username or password");
}
@GetMapping("/info")
public User info(@RequestHeader("Authorization") String token) {
String username = JwtUtil.getUsernameFromToken(token.substring(7));
return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
}
}
启动项目后,可以使用Postman或其他工具测试API。首先,调用/user/login
接口获取JWT令牌,然后在请求其他接口时在Header中添加Authorization: Bearer <token>
。
通过Spring Boot、JWT、Shiro和MybatisPlus的结合,我们快速搭建了一个功能完善的后端脚手架。这个脚手架不仅支持用户认证和授权,还提供了Restful风格的API接口。希望本文能帮助你快速上手这些技术,并在实际项目中应用它们。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。