前言:html
shiro由于其简单、可靠、实现方便而成为如今最经常使用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登陆注销功能使用以外,也会根据惯例在文章最后总结一下shiro的大体配置使用流程,但愿本篇文章可以给你们一种原来shiro是这么简单的错觉感受。java
注意:该篇文章的开始是创建在一个完备的spring+mybatis的开发环境中,除了shiro以外的配置基本不会涉及到。作好本身--eguid原创文章web
shiro补充以及shiro注解问题解决文章(但愿对你们有用):shiro与spring整合详解与spring项目中shiro注解不生效的解决办法spring
本篇文章使用shiro-1.4.0版本apache
一、shiro官方下载地址:http://shiro.apache.org/download.html数组
二、maven依赖项:安全
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
<!-- shiro过滤器 --> <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>/*</url-pattern> </filter-mapping>
注意事项:spring在加载上下文的时候,是没有扫描注解的,因为咱们在自定义的realm中用到了spring的注解,因此须要在shiro的自定义realm以前进行注解扫描。session
<context:component-scan base-package="cc.eguid" />mybatis
<!-- shiro的生命周期处理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 使用shiro安全检查注解 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> <!-- 自定义的安全数据源,用来实现自定义的登陆验证、角色验证、权限验证 --> <bean id="myRealm" class="cc.eguid.shiro.MyRealm"/> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> </bean> <!-- shiro过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 配置安全管理器 --> <property name="securityManager" ref="securityManager" /> <!-- 身份认证失败跳转的地址,没有登陆固然就跳转到登陆地址 --> <property name="loginUrl" value="/login/" /> <!-- 身份认证成功跳转的地址,通常登陆成功后会跳转到系统首页 --> <property name="successUrl" value="/" /> <!-- 权限认证失败跳转的地址 ,用来提示当前用户没有操做权限,能够不须要--> <property name="unauthorizedUrl" value="/login/unauthorized" /> <property name="filterChainDefinitions"> <!--anon 表示匿名访问,不须要认证以及受权 --> <!--authc表示须要认证 没有进行身份认证是不能进行访问的 --> <!--authc,roles[admin]表示是admin角色的用户才能访问 --> <value> /* = authc /static/** =anon /login/** = anon /admin/** = authc,roles[admin] /camera/** = authc /** = authc </value> </property> </bean>
过滤器里能够配置注释里写的很清楚,anon表示匿名访问,authc表示须要进行登陆验证、权限验证、角色验证app
自定义realm实现请看下面。
public class MyRealm extends AuthorizingRealm{ Logger log=Logger.getLogger(MyRealm.class); @Autowired private UserService userService;//这是本身实现的用户信息操做类,实现用户信息,用户角色信息、用户权限信息查询功能 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { log.info("从登陆凭证中获取用户信息,因为咱们在doGetAuthenticationInfo中直接在principals中存放的用户信息对象,因此咱们能够得到当前用户信息"); UserInfo user = (UserInfo) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 查询角色信息 Collection<String> roles = userService.findRoles(user); log.info("查询用户角色信息并添加到shiro权限验证器中,一个用户能够对应多个角色"); info.addRoles(roles); // 查询权限信息 Collection<String> permissions = userService.findPermissions(user); log.info("把用户权限信息添加到shiro权限过滤器中"); info.addStringPermissions(permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{ log.info("shiro登陆验证"); // 在咱们本身的登陆流程中应该确保登陆的用户信息已经插入AuthenticationToken中,这样才能经过shiro的认证流程 String loginname= token.getPrincipal().toString(); //虽然在登陆流程中咱们给的是String的面,可是shiro中已经写死了密码是个字符数组,因此老老实实的把密码转成char[]吧 char[] password=(char[]) token.getCredentials(); // 查询用户名对应的用户信息 UserInfo user =userService.queryUserInfoByLoginName(loginname); log.info("验证用户信息:"+loginname+","+user+"密码:"+password); if (user != null&&user.getPassword()!=null) { //直接把用户信息对象和密码塞进shiro验证器,shiro会自动判断密码是否正确 AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, password, getName()); return authenticationInfo; } return null; }
3、shiro登陆和注销流程实现
/** * shiro注销,shiro会自动把session释放,因此不须要调用session.invalidate();方法 */ @Override public void logout(){ Subject currentUser = SecurityUtils.getSubject(); currentUser.logout(); } /** * shiro登陆 */ @Override public boolean singin(UserInfo user){ try{ Subject subject = SecurityUtils.getSubject() ; UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginusername(),user.getPassword()) ; subject.login(token); log.info("shiro登陆验证成功"); return true; }catch(AuthenticationException e){ log.error("shiro登陆验证不经过",e); return false; } } /** * 判断用户是否登陆(shiro方式) */ @Override public boolean isSignon() { Subject subject = SecurityUtils.getSubject() ; return subject.isAuthenticated(); }
/** * 从shiro中获取当前登陆的用户信息 */ @Override public UserInfo getCurrentUserInfo(){ Subject subject = SecurityUtils.getSubject() ; return (UserInfo) subject.getPrincipal(); }
以上,但愿对你们有所帮助。-- 作好本身--eguid