1.整体流程
1》subject 封装了用户名密码,用户权限,用户角色等信息
2》securitymanager负责进行校验用户名密码,权限等操作
3》realm,相当于securitymanager的数据源,去数据库查询,将权限,是否登录成功等信息提供给secutirymanager
流程如图
2.前后端不分离,代码实现
需要自定义realm shiro配置类
1》shiro配置类
配置securitymanager 使用自定义realm
配置默认的ShiroFilterFactoryBean 设置拦截路径和权限
package com.example.shiro78.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.text.IniRealm;
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.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Autowired
MyRealm myRealm;
public MyRealm getmyrealm() {
// myRealm.setCredentialsMatcher(getCredentialsMatcher());
return myRealm;
}
// @Bean
// public HashedCredentialsMatcher getCredentialsMatcher() {
用来指定加密规则
// HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
// matcher.setHashAlgorithmName("MD5");
// matcher.setHashIterations(1);
// return matcher;
// }
//配置thmymeleaf方言
@Bean
public ShiroDialect getshirodialect() {
return new ShiroDialect();
}
// 创建securitymanager
@Bean
public DefaultWebSecurityManager getdefaultWebSecurityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
// defaultWebSecurityManager.setCacheManager(getehacche());
defaultWebSecurityManager.setRealm(getmyrealm());
return defaultWebSecurityManager;
}
// 设置拦截器,作用是设定什么路径需要什么样的权限(未登录可访问的路径,登录后可访问的路径)
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager defaultSecurityManager) {
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
filter.setSecurityManager(defaultSecurityManager);
Map<String, String> filtermap = new HashMap<>();
// anon匿名用户可以访问
// authc 认证用户可以访问
// user 使用rememberme的用户可以访问
// perms 对应权限可以访问
// role 对应的角色可以访问
// 注意注意!!!! 这里只是拦截的路径,还需要写控制器让路径对应页面
filtermap.put("/", "anon");
filtermap.put("/login", "anon");
filtermap.put("/login.html", "anon");
filtermap.put("/user/login", "anon");
filtermap.put("/index.html", "anon");
// filtermap.put("/dingdan/add", "anon");
filtermap.put("/user/regist", "authc");
filtermap.put("/regist", "anon");
filtermap.put("/static/**", "anon");
filtermap.put("/norenzheng", "anon");
// 新增订单权限
filtermap.put("/dingdan/add", "perms[sys:x:save]");
filtermap.put("/norenzheng.html", "anon");
filtermap.put("/exit", "logout");
filter.setFilterChainDefinitionMap(filtermap);
// 当访问autch的页面时,未登录,跳转的页面
filter.setLoginUrl("/nologin");
// 当访问需要具体权限时,未登录,或者权限不足时跳转的页面
filter.setUnauthorizedUrl("/norenzhenghuobuzu");
return filter;
}
//配置注解管理权限 ,记住就好
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(getdefaultWebSecurityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator autoproxycreator = new DefaultAdvisorAutoProxyCreator();
autoproxycreator.setProxyTargetClass(true);
return autoproxycreator;
}
// // 配置缓存管理 避免进行多次对数据库的查询
// @Bean
// public EhCacheManager getehacche() {
// EhCacheManager ehCacheManager = new EhCacheManager();
// ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
// return ehCacheManager;
// }
@Autowired
DataSource dataSource;
// public JdbcRealm getjdbcrealm() {
// JdbcRealm jdbcRealm = new JdbcRealm();
// jdbcRealm.setDataSource(dataSource);
// return jdbcRealm;
// }
//
// public IniRealm getiniRealm() {
// IniRealm iniRealm = new IniRealm("E:\\java\\shiro\\shiro7.8\\src\\main\\resources\\Shiro.ini");
// return iniRealm;
// }
}
2》配置自定义realm
重写认证方法和查询权限角色方法
package com.example.shiro78.config;
import com.example.shiro78.dao.UserMapper;
import com.example.shiro78.pojo.User;
import com.example.shiro78.service.Checklogin;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
@Service
public class MyRealm extends AuthorizingRealm {
@Autowired
UserMapper userMapper;
public String getrealmname() {
return "MyRealm1";
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取当前已经登录用户的用户名
String uname = (String) principalCollection.iterator().next();
Set<String> permissions = userMapper.querypermission(uname);
Set<String> roles = userMapper.queryrole(uname);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
System.out.println("角色是" + roles);
System.out.println("权限是" + permissions);
// 将权限信息返回权限管理器
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
String uname = usernamePasswordToken.getUsername();
User user = userMapper.checklogin(uname);
if (user == null) {
return null;
}
AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getrealmname());
// 将认证信息返回认证器
return info;
}
}
1,2 5处的代码是 ShiroConfig 类的 ShiroFilterFactoryBean 的 filtermap.put("/...", "....");
判断是否放行
3处的代码是程序员自己调用的,如下
@Service
public class Checklogin {
public void checklogin(String username,String password) throws Exception
{
UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
Subject subject= SecurityUtils.getSubject();
subject.login(usernamePasswordToken);
}
}
4处的代码是在controller层添加注解
//需要某个权限才可以访问
@RequiresPermissions("sys:x:delete")
@ResponseBody
@RequestMapping("/dingdan/del")
public String deldingdan() {
return "具有删除订单权限";
}
//需要某个角色才可以访问
@RequiresRoles("cmanager")
@ResponseBody
@RequestMapping("/cmanager")
public String cmanager() {
return "具有cmanager角色";
}
// 需要登录后才可以访问
@RequiresAuthentication
@ResponseBody
@RequestMapping("/login")
public String testerror() {
return "登录成功";
}