shiro原理流程图

shiro授权方式
-
编程式:通过写if/else 授权代码块完成【ini配置文件】
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
-
注解式:通过在执行的Java方法上放置相应的注解完成
@RequiresRoles("admin")
public void hello() {
//有权限
}
-
JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成
<shiro:hasRole name="admin">
<!— 有权限—>
</shiro:hasRole>
-
自定义realm大致流程

shiro配置与详解
-
pom 导入
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.3</version>
</dependency>
-
web.xml
<!-- 配置Shiro过滤器 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由servlet container管理 -->
<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>
-
applicationContext-shiro.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- realm实现,继承自AuthorizingRealm -->
<bean id="userRealm" class="org.j.shiro.security.UserRealm"/>
<bean id="emailRealm" class="org.j.shiro.security.EmailRealm"/>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.j.shiro.session.UserSessionManager">
<property name="globalSessionTimeout" value="1800000"></property>
<property name="sessionDAO" ref="sessionDAO"/>
<property name="sessionValidationSchedulerEnabled" value="true"></property>
<property name="sessionIdUrlRewritingEnabled" value="false"></property>
<property name="sessionListeners">
<list><ref bean="sessionListener"/></list>
</property>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="sessionManager" ref="sessionManager"></property>
<!-- <property name="realm" ref="userRealm"/> -->
<!-- 配置多个Realm -->
<property name="authenticator" ref="authenticator"></property>
</bean>
<!-- 配置多个Realm -->
<!-- org.apache.shiro.authc.pam.ModularRealmAuthenticator -->
<bean id="authenticator" class="org.j.shiro.security.MyModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="userRealm"/>
<ref bean="emailRealm"/>
</list>
</property>
</bean>
<!-- Shiro过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/authadmin/login.html"/>
<property name="successUrl" value="/authadmin/index.html"/>
<property name="unauthorizedUrl" value="/WEB-INF/view/error/403.html"/>
<property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
</bean>
<!--自定义filterChainDefinitionMap -->
<bean id="chainDefinitionSectionMetaSource" class="org.j.shiro.security.ChainDefinitionSectionMetaSource">
<property name="filterChainDefinitions">
<value>
/favicon.ico=anon
/statics/**=anon
/WEB-INF/view/error/**=anon
/login.html=anon
/upload/**=anon
/sys/login=anon
/sys/**=authc
/authadmin/login.html=anon
</value>
</property>
</bean>
<!-- 会话DAO -->
<bean id="sessionDAO" class="org.j.shiro.session.UserSessionDAO"/>
<!-- 会话监听器 -->
<bean id="sessionListener" class="org.j.shiro.listener.UserSessionListener"/>
<!-- session工程 -->
<bean id="sessionFactory" class="org.j.shiro.session.UserSessionFactory"/>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 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>
分析执行流程

@ResponseBody
@RequestMapping(value = "/sys/login", method = RequestMethod.POST)
public R login(String username, String password, String captcha)throws IOException {
String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
if(!captcha.equalsIgnoreCase(kaptcha) && false){
return R.error("验证码不正确");
}
try{
Subject subject = ShiroUtils.getSubject();
password = MD5Utils.encrypt(username, password);//sha256加密
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);//提交认证
}catch (UnknownAccountException e) {
return R.error(e.getMessage());
}catch (IncorrectCredentialsException e) {
return R.error(e.getMessage());
}catch (LockedAccountException e) {
return R.error(e.getMessage());
}catch (AuthenticationException e) {
return R.error("账户验证失败");
}
return R.ok();
}
public class ShiroRealm extends AuthorizingRealm{
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
/**
* 授权【验证权限时调用】
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Object principal = principals.getPrimaryPrincipal();
Long userId = ShiroUtils.getUserId();
//查询用户角色
Set<String> rolesSet = userService.listUserRoles(userId);
//查询用户权限
Set<String> permsSet = userService.listUserPerms(userId);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(rolesSet);
info.setStringPermissions(permsSet);
return info;
}
/**
* 认证【登陆时调用】
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken utoken = null;
if (token instanceof UsernamePasswordToken) {
utoken = (UsernamePasswordToken) token;
} else {
return null;
}
String username = (String) utoken.getPrincipal();
String password = new String((char[]) utoken.getCredentials());
// 根据用户名查询用户信息
User user = userMapper.findUserByUsername(username);
// 账户不存在
if (user == null) {
throw new UnknownAccountException("账号或密码不正确");
}
// 需要判断密码是否错误
if (!password.equals(user.getUserPwd())) {// 可加逻辑判断
throw new IncorrectCredentialsException("账号或密码不正确");
}
// 需要判断账号是否启用
if (user.getUserStatus() == 0) {
throw new LockedAccountException("账号已被锁定,请联系管理员");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
}
-
shiro自定义工具类
public class ShiroUtils {
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
public static SysUserEntity getUserEntity() {
SysUserEntity user = (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
return user==null?(SysUserEntity)getSessionAttribute("user"):user;
}
public static Long getUserId() {
return getUserEntity().getUserId();
}
public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}
public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}
public static boolean isLogin() {
return SecurityUtils.getSubject().getPrincipal() != null;
}
public static void logout() {
SecurityUtils.getSubject().logout();
}
public static String getKaptcha(String key) {
String kaptcha = getSessionAttribute(key).toString();
getSession().removeAttribute(key);
return kaptcha;
}
}
-
MD5工具类
public class MD5Utils {
private static final String SALT = "asd6af1lks";
private static final String ALGORITH_NAME = "md5";
private static final int HASH_ITERATIONS = 2;
/**
* 使用md5生成加密后的密码
* @param user
* @return
*/
public static String encrypt(String pswd) {
String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(SALT), HASH_ITERATIONS).toHex();
return newPassword;
}
/**
* 使用md5生成加密后的密码
* @param user
* @return
*/
public static String encrypt(String username, String pswd) {
String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(username + SALT), HASH_ITERATIONS).toHex();
return newPassword;
}
}
未完待续