结合《spring项目框架的搭建(1):基本搭建》代码,在此基础上完成shiro的整合。java
整合前的准备web
<!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</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>
<shiro.version>1.4.0</shiro.version> 表示shiro使用的版本号,这里使用的当前时间的最新版本。spring
新建一个ShiroDbRealm.java类继承AuthorizingRealm,复写父类中的两个方法apache
doGetAuthorizationInfo,AuthenticationInfo;使用 @Component注解将对象交给容器管理。api
伪代码以下:缓存
/** * 受权查询回调函数, 进行鉴权但缓存中无用户的受权信息时调用. */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //获取当前登陆的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next() String currentUsername = (String)super.getAvailablePrincipal(principals); Admin admin=adminService.findByUserName(currentUsername); List<String> roles = new ArrayList<String>();//存放该用户具有的角色 List<String> permissions = new ArrayList<String>();//存放该用户具有的权限 //查询用户拥有的角色和对应的权限 List<AdminRole> adminRolesList=adminRolesService.findByAdminId(admin.getId()); if(adminRolesList!=null && adminRolesList.size()>0){ Role role; for (AdminRole adminRoles:adminRolesList){ role=roleService.get(Role.class,adminRoles.getRoleId()); roles.add(role.getRoleName()); RolePermission permission=roleService.findRolePermission(role.getId()); if (permission!=null){ permissions.addAll(permission.getPermissionList()); } } } //用来保存认证好的信息, SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); if (admin.getIdentity()==1){ info.addRole("admin"); info.addStringPermission("*:*"); }else { info.addRoles(roles); info.addStringPermissions(permissions); } return info; } /** * 认证回调函数,登陆时调用. */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken; Admin admin=adminService.findByUserName(token.getUsername()); if (admin!=null){ return new SimpleAuthenticationInfo(admin.getUsername(),admin.getPassword(),admin.getRealName()); }else { return null; } }
AuthenticationInfo登陆成后会执行此方法,可是须要在登陆成功后的位置显示调用subject.login(token).安全
身份认证成功后会进入doGetAuthorizationInfo进行权限认证和存储。session
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> <description>Shiro安全配置</description> <!-- Shiro 安全管理器--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="shiroDbRealm"/> </bean> <!-- Shiro 过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--shiro 核心权限管理器 必须配置--> <property name="securityManager" ref="securityManager"/> <!--身份认证失败跳转的登陆页面--> <property name="loginUrl" value="/admin/login"/> <!--认证成功跳转的指定页面--> <property name="successUrl" value="/admin/index"/> <!--权限认证失败跳转的指定页面--> <property name="unauthorizedUrl" value="/admin/unautho"/> <!--url 过滤规则--> <property name="filterChainDefinitions"> <value> /admin/login = anon /admin/doLogin = anon /admin/logout = authc /admin/unautho=anon <!--/admin/** = [*:*]--> </value> </property> </bean> <!-- 保证明现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 开启Shiro注解 AOP式方法级权限检查 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"/> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> </beans>
同时在spring.xml中添加 <import resource="spring-shiro.xml"/>app
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
@RequestMapping(value = "doLogin",method = RequestMethod.POST) public ApiBean doLogin(String username, String password, Boolean rememberMe, HttpSession session, HttpServletRequest request){ ApiBean apiBean; if (StrKit.notNull(username,password)) { //验证用户名密码是否正确 JSONObject loginRes=adminService.login(username,password); if (loginRes.getBoolean("login")){ Admin admin= (Admin) loginRes.get("admin"); UsernamePasswordToken token = new UsernamePasswordToken(admin.getUsername(),admin.getPassword()); Subject subject = SecurityUtils.getSubject(); subject.login(token); apiBean= ApiBean.responseSuccess("登陆成功"); } else { apiBean= ApiBean.responseError(loginRes.getString("msg")); } } else { apiBean= ApiBean.responseError("用户名密码错误"); } return apiBean; }
当subject.login(token)以后,会进入到自定义的realm中的AuthenticationInfo方法,该方法执行完成后会执行doGetAuthorizationInfo方法。在这里我显示的调用了service里的方法去验证用户名密码是否正确,在正确以后再将用户交由shiro进行二次身份核实和权限认证。框架