这是 Shiro 的问题吗?

2020-04-24 18:51:33 +08:00
 skai0dev

最近学 Thymeleaf 的时候做一个登录的页面,后端是用 Shiro 进行认证的,但不知道为什么 BindingResult 里面的 FieldError 一直不显示,如果不用 Shiro 的话就可以,有人遇到过一样的情况吗? 附上关键的代码(篇幅有点长):

ShiroConfig.java:

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/**", "anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    
    @Bean
    public AccountRealm accountRealm() {
        AccountRealm accountRealm = new AccountRealm();
        return accountRealm;
    }

    @Bean
    public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(accountRealm());
        return securityManager;
    }
}

AccountRealm.java

public class AccountRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String) authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());
        if (!username.equals("admin")) {
            throw new UnknownAccountException("用户不存在");
        }
        if (!"root.".equals(password)) {
            throw new IncorrectCredentialsException("密码不正确");
        }
        AccountDO account = new AccountDO(1, username, password);
        return new SimpleAuthenticationInfo(account, password, getName());
    }
}

AccountDO.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AccountDO {
    private Integer id;
    @Size(min = 5, message = "用户名长度不能小于 5")
    @NotBlank(message = "用户名不能为空")
    private String username;
    @Size(min = 4, max = 18, message = "密码长度为 4 到 18 位")
    @NotBlank(message = "密码不能为空")
    private String password;
}

AccountController.java


@Controller
@Slf4j
public class AccountController {
    @GetMapping(value = "/login")
    public String login(Model model) {
        AccountDO account = new AccountDO();
        model.addAttribute("account", account);
        return "login";
    }

    @PostMapping(value = "/login")
    public String login(@Valid AccountDO account,
                        BindingResult bindingResult,
                        Model model) {
        model.addAttribute("account", account);
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors().forEach((error) -> log.info(error.getDefaultMessage()));
            return "login";
        }
        UsernamePasswordToken token = new UsernamePasswordToken(account.getUsername(), account.getPassword());
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            AccountDO accountDO = (AccountDO) subject.getPrincipal();
            log.info("登录成功:" + accountDO.getUsername());
            return "index";
        } catch (UnknownAccountException e) {
            FieldError fieldError = new FieldError("account", "username", e.getMessage());
            bindingResult.addError(fieldError);
            log.info(e.getMessage());
            return "login";
        } catch (AuthenticationException e) {
            FieldError fieldError = new FieldError("account", "password", e.getMessage());
            bindingResult.addError(fieldError);
            log.info(e.getMessage());
            return "login";
        }
    }
}

login.html

<form th:action="@{/login}" method="post" th:object="${account}">
    <table>
        <tbody>
            <tr>
                <td>用户名</td>
                <td><input type="text" name="username" th:value="*{username}" required></td>
                <td><span th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></span></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" name="password" th:value="*{password}" required></td>
                <td><span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span></td>
            </tr>
            <tr>
                <td><button type="submit">登录</button></td>
            </tr>
        </tbody>
    </table>
</form>

不管是抛异常的时候加入的 FieldError 还是实体类验证时 BindingResult 里的 FieldError 都不能显示。试了一下不用 Shiro 的话可以显示,这是为什么呢?

1615 次点击
所在节点    Java
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/665794

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX