Shiro安全矿建是目前最常用的作为登录注册的框架,提供了认证、授权、加密、和会话管理等功能;
Shiro的功能点:
认证:验证用户身份;
授权:对用户执行访问控制:判断用户是否被授权做某事;
会话管理:在任何环境下使用SessionAPI,即使没有Web或EJB容器;
加密:以更简洁易用的方式使用加密功能,保护或隐藏数据防止被偷窥;
Realms:聚集一个或多个用户安全数据的数据源;
单点登录:(SSO)功能;
为没有关联到登录的用户启用Remember Me服务。
Shiro的四大核心部分:(重点)
Authentication(身份验证):简称为“登录”,即证明用户的身份;
Authorization(授权):访问控制的过程,即决定是否有权限去访问手保护的资源;
Session Management(会话管理):管理用户特定的会话,即使在非Web或EJB应用程序。
Cryptography(加密):通过使用加密算法保持数据安全;
Shiro的三个核心组件:
Subject:正与系统进行交互的用户或者服务。所有的Subject实例必须被绑定到一个SecurityManager上。
SecurityManager:Shiro架构的核心,用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当Shiro与一个Subject进行交互时。实质上是幕后的SecurityManager处理所有繁重的Subject安全操作。
Realms:本质上是一个特定安全的DAO。当配置Shiro时,必须指定至少一个Realm用来进行身份验证及授权。Shiro提供了多重可用的Realms来获取安全相关的数据。如关系数据库JDBC或属性文件等。可以定义自己Realms实现来代表自定义的数据源。
一、shiro整合Spring(此处以maven项目为例)
首先在pom.xml中添加jar包依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency>
准备基本的配置文件在spring配置文件中做如下配置:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/mvc/login.xhtml"/> <property name="successUrl" value="/mvc/index.xhtml"/> <property name="filterChainDefinitions"> <value> /mvc/mallszccb/pd/**/**/**/0/**/** = authc /mvc/docs/** = authc, perms[document:read] /currentUser = authc /** = anon </value> </property> </bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm"/> </bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <bean id="myRealm" class="com.ifunpay.portal.security.MemberUserRealm"/>
配置文件准备完毕之后开始写Realm类,该方法必须继承AuthorizingRealm:
public class MemberUserRealm extends AuthorizingRealm { public static final String SALT = Sha256Hash.ALGORITHM_NAME; @Resource MemberUserService memberUserService; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; String username = usernamePasswordToken.getUsername(); MemberUserEntity memberUserEntity = memberUserService.getEntityByName(username); if(memberUserEntity != null){ return new SimpleAuthenticationInfo(username, memberUserEntity.getPassword(), getSaltByteSource(), getName()); }else{ return null; } } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } public static String encryptPassword(Object password) { return new SimpleHash(SALT, password, getSaltByteSource()) .toBase64(); } private static ByteSource getSaltByteSource() { return ByteSource.Util.bytes(SALT); } }
而后我在这里写了一个service来做登录业务:
@Component public class ShiroSecurityService { public void auth(String username, String password){ UsernamePasswordToken token = new UsernamePasswordToken(username, MemberUserRealm.encryptPassword(password)); SecurityUtils.getSubject().login(token); } }
最后在controller层做一个login来做shiro验证就ok了:
@RequestMapping(value = "/login", method = RequestMethod.POST) public String auth(@RequestParam String username, @RequestParam String password) { try { SavedRequest savedRequest = (SavedRequest) SecurityUtils.getSubject().getSession().getAttribute("shiroSavedRequest"); String uri = savedRequest.getRequestURI(); shiroSecurityService.auth(username, password); logger.info("login success"+uri); return "redirect:"+uri; } catch (Exception e) { logger.error("", e); return "redirect:/mvc/errorLogin?msg="+e.getMessage(); } }