shiro学习笔记(6)--spring集成及可能遇到的问题小结

上篇spring集成shiro后续…
spring集成shiro主要是org.apache.shiro.web.filter.authc.FormAuthenticationFilter类。
1、controller

@Controller
public class HelloSsm {

    @RequestMapping(value = {"/","tologin.do"})
    public String tologin(){
        return "models/sys/login";
    }

    @RequestMapping("login.do")
    public String login(Model model, User user, HttpServletRequest request){
        //进入login.do说明shiro认证失败
        /**
         * 在FormAuthenticationFilter中,将认证失败的异常类信息保存在request的shiroLoginFailur中
         */
        String className = (String) request.getAttribute("shiroLoginFailure");
        if(UnknownAccountException.class.getName().equals(className)){
            System.out.println("账号有误!");
        }else if(DisabledAccountException.class.getName().equals(className)){
            System.out.println("禁用的账号!");
        }else if(ExcessiveAttemptsException.class.getName().equals(className)){
            System.out.println("登录次数过多!");
        }else if(ConcurrentAccessException.class.getName().equals(className)){
            System.out.println("并发访问异常!");
        }else if(IncorrectCredentialsException.class.getName().equals(className)){
            System.out.println("密码错误!");
        }else if(ExpiredCredentialsException.class.getName().equals(className)){
            System.out.println("密码过期!");
        }else {
            System.out.println("系统错误");
        }
        String message = "账号或密码错误,请重试...";
        request.setAttribute("message",message);
        return "models/sys/login";
    }

    @RequestMapping("index.do")
    public String index(Model model,HttpServletRequest request){
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if(user!=null) {
            request.setAttribute("username", user.getUsername());
        }
        return "models/sys/index";
    }
}

2、login.jsp
注意:form提交表单需要post方式,否则FormAuthenticationFilter将无法进入自定义realm中的认证方法。

<form action="login.do" style="background-color: burlywood" method="post">
    username:<input type="text" name="username"><br/>
    password:<input type="password" name="password"><br/>
    <c:if test="${message!=null && message!=''}">
        <input type="text" value="${message}" style="font-weight: bold;font-size:10px;">
    </c:if>
    <input type="submit" value="login">
</form>

3、跑起来,你可能会碰到的坑~
(1)无法进入realm的认证方法
查看表单提交方式是否是post
(2)无法注入service
这个问题曾困扰了好久,原因有很多。
首先是web容器中filter加载优先于servlet,为此在filter中无法使用spring注解,需要将spring加载优先级设置更高(当然也可能无效)
其次:仍然无效时需要通过工具类获取spring上下文,以获取需要注入的service

loginService = SpringBeanFactoryUtils.getBean(LoginService.class);
@Component
public class SpringBeanFactoryUtils implements ApplicationContextAware{

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringBeanFactoryUtils.applicationContext == null) {
            SpringBeanFactoryUtils.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //根据名称(@Resource 注解)
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //根据类型(@Autowired)
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

(3)loginUrl和successUrl及filterChainDefinitions配置
注意路径设置与认证不要冲突
(4)认证失败
首先是确保是否获取了完整的用户信息。在realm的认证入参AuthenticationToken中查看
其次是断点跟踪认证是否正常
(5)认证完成跳转路径
认证后跳转路径是根据shiro的xml配置确定的,个人建议最好设置successUrl。这样当认证失败时可完整记录失败异常信息
说一下认证失败时信息获取:

/**
   * 在FormAuthenticationFilter中,将认证失败的异常类信息保存在request的shiroLoginFailur中
   */
        String className = (String) request.getAttribute("shiroLoginFailure");

猜你喜欢

转载自blog.csdn.net/cccp_2009/article/details/82628795
今日推荐