配置shiro
@Configuration
public class ShiroConfig {
@Bean(name="myRealm")
public Realm myRealm(){
return new ShiroRealm();
}
@Bean(name="webSecurityManager")
public DefaultWebSecurityManager webSecurityManager(){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(myRealm());
return manager;
}
@Bean(name="shiroFilter") //name不配置时默认使用方法名
public ShiroFilterFactoryBean shiroFilter(){
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(webSecurityManager());
shiroFilter.setLoginUrl("/system/login");
shiroFilter.setSuccessUrl("/index");
shiroFilter.setUnauthorizedUrl("/system/login?type=1");
//DefaultFilterChainManager 默认的拦截器管理 会添加DefaultFilter中默认的拦截器
//以前新增的自定义拦截器会添加到DefaultFilterChainManager中
Map<String,Filter> filters = new LinkedHashMap<>();
filters.put("api",new Interceptor());
shiroFilter.setFilters(filters);
Map<String,String> def = new LinkedHashMap<>();//必须使用LinkedHashMap。。。按顺序的权限排列
def.put("/common/**","anon");
def.put("/api/**","api");//自定义的拦截器匹配
def.put("/page/**","anon");
def.put("/accessToken/**","anon");
def.put("/system/logout","logout");
def.put("/system/login*","anon");
def.put("/**","user");//user表示认证通过或者通过记住我登录都能操作
shiroFilter.setFilterChainDefinitionMap(def);
return shiroFilter;
}
@Bean
public AuthorizationAttributeSourceAdvisor openShiroAnnotation(){//开启shiro注解
/*权限注解
表示当前 Subject 已经通过 login 进行了身份验证;即 Subject. isAuthenticated()返回 true。
表示当前 Subject 已经身份验证或者通过记住我登录的。
表示当前 Subject 没有身份验证或通过记住我登录过,即是游客身份。
表示当前 Subject 需要角色 admin 和 user。
表示当前 Subject 需要权限 user:a 或 user:b。
@RequiresAuthentication
@RequiresUser
@RequiresGuest
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
@RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR*/
AuthorizationAttributeSourceAdvisor attr = new AuthorizationAttributeSourceAdvisor();
attr.setSecurityManager(webSecurityManager());
return attr;
}
}
自定义的Filter(//如果使用WebMvcConfigurerAdapter的addInterceptors来实现拦截,如果shiro判断为anno的类型,此时不会再执行定义的addInterceptors拦截器)
public class Interceptor extends AdviceFilter {//AdviceFilter 提供类似springmvc aop的功能,即拦截器
@Override
protected boolean preHandle(ServletRequest req, ServletResponse response) throws Exception {
//进行额外的拦截操作
return true;
}
}
shiro需要自己编写realm来实现权限的初始化
public class ShiroRealm extends AuthorizingRealm {
@Resource
AdminUserService userService;
@Resource
ResourceService resourceService;
/*
* 登录信息和用户验证信息验证(non-Javadoc)
* subject.login时执行
* @see
* org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.
* apache.shiro.authc.AuthenticationToken)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String loginId = (String) token.getPrincipal(); // 得到用户名
String password = new String((char[]) token.getCredentials()); // 得到密码
Adminuser user = userService.login(loginId);
if(user == null) throw new UnknownAccountException("用户不存在");
if(!user.getPwd().equals(password)) throw new IncorrectCredentialsException("用户名或密码错误");
if(user.getLockStatus().equals(Constant.BOOLEAN_TRUE)) throw new LockedAccountException("用户被禁用");
List<Set<Resources>> result = userService.findMenus(user);
if(result == null || result.isEmpty()) throw new UnknownAccountException("权限不足");
ActiveUser activeUser = new ActiveUser(user.getId(), user.getUsername(), result.get(0),result.get(1));
this.setSession(Constant.SESSION_ADMINUSER, user);
return new SimpleAuthenticationInfo(activeUser, password, getName());
}
/*
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法
*/
@SuppressWarnings("unchecked")
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取身份信息
/*ActiveUser user = (ActiveUser) principals.getPrimaryPrincipal();
String uid = user.getUserId();
Set<String> permissions = userService.findPermission(uid);*/
Adminuser user = (Adminuser) this.getSession(Constant.SESSION_ADMINUSER);
String key = "shiro_permission_"+user.getId();
Set<String> permissions = null;
Object res = Memcached.get(key);
if(res == null){
permissions = userService.findPermission(user);
Memcached.put(key, permissions);
System.err.println("数据库加载====================");
}
else{
permissions = (Set<String>) res;
System.err.println("缓存获取");
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
}
登录表单提交数据
public ModelAndView login(HttpServletRequest req, @RequestParam(required=true)String loginId,@RequestParam(required=true)String password,String returnUrl,RedirectAttributes rAttr){
ModelAndView view = new ModelAndView("redirect:/system/login");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(loginId, password);
try {
//token.setRememberMe(true);//记住我
subject.login(token);
if(subject.isAuthenticated())
view.setViewName("redirect:/index");
} catch (AuthenticationException e) {
rAttr.addFlashAttribute("tips",e.getMessage());
}
return view;
}