Spring Boot Shiro前后端分离实现教程

1. 整体流程

下面是实现Spring Boot Shiro前后端分离的整体流程:

flowchart TD
    A(前端发送登录请求) --> B(后端验证用户名和密码)
    B --> C{验证成功?}
    C -->|是| D(生成Token并返回给前端)
    C -->|否| E(返回错误信息给前端)
    D --> F(前端保存Token)
    F --> G(前端发送请求带上Token)
    G --> H(后端验证Token)
    H --> I{验证成功?}
    I -->|是| J(返回请求数据给前端)
    I -->|否| K(返回错误信息给前端)

2. 具体步骤

步骤1:创建Spring Boot项目

首先,我们需要创建一个Spring Boot项目作为后端服务。可以使用Spring Initializr(

步骤2:引入相关依赖

在项目的pom.xml文件中添加以下依赖,用于集成Spring Boot和Shiro:

<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-starter</artifactId>
        <version>1.7.1</version>
    </dependency>
    ...
</dependencies>

步骤3:配置Shiro

在application.properties或application.yml文件中添加Shiro的相关配置,例如数据库连接信息、密码加密方式等。

步骤4:创建用户实体

创建一个用户实体类,用于存储用户信息。可以参考以下代码:

@Entity
@Table(name = "user")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String username;

    private String password;

    // 省略其他字段、getter和setter方法
}

步骤5:实现用户认证和授权逻辑

创建一个自定义的Shiro Realm类,实现用户认证和授权的逻辑。可以参考以下代码:

@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    // 用户认证
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        User user = userService.findByUsername(username);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 设置用户的角色和权限信息
        authorizationInfo.setRoles(user.getRoles());
        authorizationInfo.setStringPermissions(user.getPermissions());
        return authorizationInfo;
    }

    // 用户授权
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("用户名不存在");
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
        return authenticationInfo;
    }
}

步骤6:实现登录接口

创建一个登录接口,接收前端发送的用户名和密码,并调用Shiro的登录方法进行认证。如果认证成功,生成并返回一个Token给前端,否则返回错误信息。

@RestController
public class LoginController {
    @Autowired
    private UserService userService;

    @Autowired
    private TokenService tokenService;

    @PostMapping("/login")
    public Result login(@RequestBody Map<String, String> map) {
        String username = map.get("username");
        String password = map.get("password");
        
        Subject currentUser = SecurityUtils.getSubject();
        try {
            currentUser.login(new UsernamePasswordToken(username, password));
        } catch (AuthenticationException e) {
            return Result.error("登录失败");
        }
        
        User user = userService.findByUsername(username);
        String token = tokenService.generateToken(user);
        
        return Result.success(token);
    }
}

步骤7:实现权限验证拦截器

创建一个权限验证拦截器,用于验证前端发送的请求是否带有有效的Token,并进行权限控制。

@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private TokenService tokenService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");