V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
skai0dev
V2EX  ›  Java

这是 Shiro 的问题吗?

  •  
  •   skai0dev · 2020-04-24 18:51:33 +08:00 · 1574 次点击
    这是一个创建于 1462 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近学 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 的话可以显示,这是为什么呢?

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1272 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:01 · PVG 02:01 · LAX 11:01 · JFK 14:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.