返回

JFinal中使用Stateless模式无状态认证和Apache Shiro结合的实战案例

后端







## 前言

JFinal是一款轻量级的Java Web框架,它以其简单、高效和易用性而著称。Apache Shiro是一个强大的安全框架,它提供了认证、授权、加密和会话管理等功能。

## Stateless模式

Stateless模式是一种无状态的认证方式,它不需要在服务器端保存任何状态信息。当用户登录时,服务器会颁发一个Token给用户,用户在后续的请求中携带这个Token就可以被服务器识别。这种方式可以有效地防止CSRF攻击和会话劫持攻击。

## Shiro的Stateless模式

Shiro也提供了Stateless模式的支持,它可以通过`IniRealm`、`JdbcRealm`和`ShiroFilter`等组件来实现。

## JFinal中使用Shiro的Stateless模式

### 1. 依赖引入

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.5.2</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>1.5.2</version>
</dependency>

### 2. 配置Shiro

```java
public class ShiroConfig extends JFinalConfig {

    @Override
    public void configConstant(Constants constants) {
        // ...
    }

    @Override
    public void configRoute(Routes routes) {
        // ...
    }

    @Override
    public void configPlugin(Plugins plugins) {
        // 创建ShiroFilter实例
        ShiroFilter shiroFilter = new ShiroFilter();

        // 设置ShiroFilter的属性
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);

        // 设置ShiroFilter的登录URL
        shiroFilter.setLoginUrl("/login");

        // 设置ShiroFilter的认证成功URL
        shiroFilter.setSuccessUrl("/index");

        // 设置ShiroFilter的认证失败URL
        shiroFilter.setUnauthorizedUrl("/401");

        // 将ShiroFilter添加到插件列表中
        plugins.add(new ShiroPlugin(shiroFilter));
    }
}

3. 创建Realm

public class StatelessRealm extends AuthorizingRealm {

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof StatelessAuthenticationToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取当前用户的角色和权限
        // ...

        // 返回AuthorizationInfo实例
        return new SimpleAuthorizationInfo(roles, permissions);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 从令牌中获取用户名和密码
        StatelessAuthenticationToken statelessToken = (StatelessAuthenticationToken) token;
        String username = statelessToken.getUsername();
        String password = statelessToken.getPassword();

        // 根据用户名查询用户
        // ...

        // 如果用户不存在或密码不正确,则抛出异常
        if (user == null || !user.getPassword().equals(password)) {
            throw new IncorrectCredentialsException();
        }

        // 返回AuthenticationInfo实例
        return new SimpleAuthenticationInfo(username, password, getName());
    }
}

4. 创建Token

public class StatelessAuthenticationToken implements AuthenticationToken {

    private String username;
    private String password;

    public StatelessAuthenticationToken(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public Object getPrincipal() {
        return username;
    }

    @Override
    public Object getCredentials() {
        return password;
    }
}

5. 登录

public void login() {
    // 获取登录用户名和密码
    String username = getPara("username");
    String password = getPara("password");

    // 创建Token
    StatelessAuthenticationToken token = new StatelessAuthenticationToken(username, password);

    // 登录
    Subject subject = getSubject();
    subject.login(token);

    // 重定向到首页
    redirect("/");
}

6. 注销

public void logout() {
    // 获取Subject
    Subject subject = getSubject();

    // 注销
    subject.logout();

    // 重定向到登录页
    redirect("/login");
}

总结

以上就是如何在JFinal中使用Shiro的Stateless模式实现认证和授权的示例。这种方式可以有效地防止CSRF攻击和会话劫持攻击,并提高系统的安全性。