diff --git a/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java b/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java new file mode 100644 index 0000000..ae2b867 --- /dev/null +++ b/src/main/java/top/fjy8018/shiro/config/ShiroConfiguration.java @@ -0,0 +1,100 @@ +package top.fjy8018.shiro.config; + +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import top.fjy8018.shiro.credentials.CredentialsMatcher; +import top.fjy8018.shiro.realm.AuthRealm; + +import java.util.LinkedHashMap; + +/** + * shiro核心配置 + * @author F嘉阳 + * @date 2018/7/6 10:29 + */ +@Configuration +public class ShiroConfiguration { + + @Bean("shiroFilter") + public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager){ + ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); + bean.setSecurityManager(manager); + + // 设置url + bean.setLoginUrl("/login"); + bean.setSuccessUrl("/index"); + bean.setUnauthorizedUrl("/unauthorized"); + + // 配置拦截 + LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); + // 主页设置拦截,第二个参数的含义在org.apache.shiro.web.filter.mgt.DefaultFilter的枚举类中,authc为表单验证 + filterChainDefinitionMap.put("/index","authc"); + // 登录页无需拦截,anon即匿名访问 + filterChainDefinitionMap.put("/login","anon"); + + bean.setFilterChainDefinitionMap(filterChainDefinitionMap); + + return bean; + } + + + @Bean("securityManager") + public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm){ + DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); + manager.setRealm(authRealm); + return manager; + } + + + /** + * 自定义的Realm + * @param matcher + * @return + */ + @Bean("authRealm") + public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher){ + AuthRealm authRealm = new AuthRealm(); + authRealm.setCredentialsMatcher(matcher); + return authRealm; + } + + /** + * 自定义密码校验规则 + * @return + */ + @Bean("credentialsMatcher") + public CredentialsMatcher credentialsMatcher(){ + return new CredentialsMatcher(); + } + + /** + * 配置spring与shiro关联,指定spring使用的SecurityManager为自定义的SecurityManager + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){ + AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); + advisor.setSecurityManager(securityManager); + + return advisor; + } + + /** + * 代理所有servlet的过滤器链 + * @return + */ + @Bean + public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ + DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); + creator.setProxyTargetClass(true); + + return creator; + } +} diff --git a/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java b/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java new file mode 100644 index 0000000..a4aa926 --- /dev/null +++ b/src/main/java/top/fjy8018/shiro/credentials/CredentialsMatcher.java @@ -0,0 +1,23 @@ +package top.fjy8018.shiro.credentials; + +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; + +/** + * 自定义校验规则 + * @author F嘉阳 + * @date 2018/7/6 10:25 + */ +public class CredentialsMatcher extends SimpleCredentialsMatcher { + + @Override + public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { + UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; + String password = new String (usernamePasswordToken.getPassword()); + String dbPassword = (String) info.getCredentials(); + // 数据库密码与用户密码匹配 + return this.equals(password,dbPassword); + } +} diff --git a/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java b/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java new file mode 100644 index 0000000..7217f91 --- /dev/null +++ b/src/main/java/top/fjy8018/shiro/realm/AuthRealm.java @@ -0,0 +1,74 @@ +package top.fjy8018.shiro.realm; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.springframework.beans.factory.annotation.Autowired; +import top.fjy8018.shiro.dataobject.Permission; +import top.fjy8018.shiro.dataobject.Role; +import top.fjy8018.shiro.dataobject.User; +import top.fjy8018.shiro.service.UserService; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author F嘉阳 + * @date 2018/7/6 10:00 + */ +public class AuthRealm extends AuthorizingRealm { + + @Autowired + private UserService userService; + + /** + * shiro登录成功后的授权方法 + * @param principalCollection + * @return + */ + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { + // 从session中取用户 + User user = (User) principalCollection.fromRealm(this.getClass().getName()).iterator().next(); + + List permissionList = new ArrayList<>(); + Set roleSet = user.getRoles(); + // 取角色 + if (CollectionUtils.isNotEmpty(roleSet)){ + for (Role role : roleSet){ + // 取权限 + Set permissionSet = role.getPermissions(); + if (CollectionUtils.isNotEmpty(permissionSet)){ + for (Permission permission : permissionSet){ + permissionList.add(permission.getName()); + } + } + + } + } + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + info.addStringPermissions(permissionList); + + return info; + } + + /** + * 认证登录 + * @param authenticationToken + * @return + * @throws AuthenticationException + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { + + UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken; + String username = usernamePasswordToken.getUsername(); + // 通过用户名查用户是否存在,合法则登录认证通过 + User user = userService.findByUsername(username); + return new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName()); + } +}