这一节说明shiro对登录模块的限制,这一节可能用到的接口有:SecurityManager,Realm,AuthenticationToken,AuthenticationInfo,PrincipalCollection,如果你对这些接口不熟悉的话,回到第一节先看看他们的大概介绍。
登录模块的大概流程很简单,用户提交用用名+密码,然后从数据库查找该用户,如果没有找到怎么样,找到了用户但是密码不对又怎么样。先将我搭建的shiro项目的pom.xml贴出,方便你的测试。在这个项目中我集成了spring+springMVC+shiro。
<properties>
<spring.version>4.1.6.RELEASE</spring.version>
<junit.version>4.11</junit.version>
<jackson.version>2.4.2</jackson.version>
<shiro.version>1.2.2</shiro.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
我们在实际项目中对shiro的使用是集成在spring中使用的,不会用到官网上提到的shiro.ini,因为没有人会将权限 角色定义在一个文档中,我将spring的xml的配置和项目的web.xml的配置贴出来,以做到我们的项目是一样的。
web.xml
<web-app>
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
spring的xml,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- override these for application-specific URLs if you like: <property
name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/home.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/> -->
<!-- The 'filters' property is not necessary since any declared javax.servlet.Filter
bean -->
<!-- defined will be automatically acquired and available via its beanName
in chain -->
<!-- definitions, but you can perform instance overrides or name aliases
here if you like: -->
<!-- <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/>
</util:map> </property> -->
<!-- <property name="filterChainDefinitions"> <value> # some example chain
definitions: /admin/** = authc, roles[admin] /docs/** = authc, perms[document:read]
/** = authc # more URL-to-FilterChain definitions here </value> </property> -->
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property
instead. -->
<property name="realm" ref="myRealm" />
<!-- By default the servlet container sessions will be used. Uncomment
this line to use shiro's native sessions (see the JavaDoc for more): -->
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<bean id="myRealm" class="realm.MyRealm" />
</beans>
其中MyRealm,因为我们这里仅仅是做登录,没有涉及到权限验证,所以直接继承自AuthenticatingRealm即可。代码如下:
public class MyRealm extends AuthenticatingRealm{
private Map<String,String> db = new HashMap<String,String>();
{
db.put("张三","aaa");
db.put("李四", "bbb");
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
final String username = (String) token.getPrincipal();
final String password = db.get(username);
if(db.get(username)==null){
throw new UnknownAccountException();
}
AuthenticationInfo info = new AuthenticationInfo() {
private static final long serialVersionUID = -1174132738824136785L;
public PrincipalCollection getPrincipals() {
SimplePrincipalCollection coll = new SimplePrincipalCollection(username,"DB");//暂时没有考虑中间修改用户名的情况
Object o = coll.getPrimaryPrincipal();//表示是从数据库中来的,这里的DB仅仅是象征意义,
System.out.println(o.getClass().getName());
return coll;
}
public Object getCredentials() {//暂时没有考虑中间修改密码的情况。
return password;
}
};
return info;
}
}
这个是访问的controller
@Controller
public class ShiroControllerLogin {
@ResponseBody
@RequestMapping("/login.do")
public String denglu(String username,String password,HttpSession session){
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject user = SecurityUtils.getSubject();
try {
user.login(token);
} catch (IncorrectCredentialsException e1) {
return "密码不正确";
}catch(UnknownAccountException e2){
return "用户名不存在";
}
/**
* 你的登陆操作假设已经完成
*/
return "成功登陆";
}
}
希望你也能做到跟我完全一样的代码,然后在下一节中我将尽可能多的查看shiro关于登录的源码。