shiro依赖 shiro-all 及 thymeleaf-extras-shiro
ShiroConfig配置类
package com.qust.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import java.util.HashMap;
import java.util.Map;
/**
* springboot支持注解注入bean,往往用于springboot不集成的第三方组件
*
*/
@Configuration
public class ShiroConfiguration {
/**
* 配置拦截器 请求认证权限 都是靠拦截器
* @param securityManager
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//登录的url
shiroFilterFactoryBean.setLoginUrl("/loginPage");
//成功后的请求
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
//过滤器
Map<String,String> map = new HashMap<>();
map.put("/loginPage","anon");
map.put("/login","anon");
//anon 无需认证
map.put("/register","anon");
//authc 必须要认证
map.put("/**","authc");
map.put("/addUser","roles[role1]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
/**
* 配置SecurityManager
* @param myRealm
* @return
*/
@Bean(name = "securityManager")
public SecurityManager getSecurityManager(MyRealm myRealm){
SecurityManager securityManager = new DefaultWebSecurityManager(myRealm);
return securityManager;
}
/**
* 创建自定义realm
* @return
*/
@Bean(name = "myRealm")
public MyRealm getMyRealm(){
return new MyRealm();
}
/**
* 配置shiro和thymelf进行整合
* @return
*/
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
自定义MyRealm
package com.qust.config;
import com.qust.entity.Role;
import com.qust.service.TeacherService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
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 java.util.List;
public class MyRealm extends AuthorizingRealm {
@Autowired
private TeacherService teacherService;
public TeacherService getTeacherService() {
return teacherService;
}
public void setTeacherService(TeacherService teacherService) {
this.teacherService = teacherService;
}
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//只有通过认证后 才可以考虑授权的问题 获取到认证后返回的信息
SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
//获取用户名
String username = getAvailablePrincipal(principalCollection).toString();
//通过用户名 获取该用户有的角色
List<Role> roles = teacherService.getRoleByName(username);
for (Role role1 : roles) {
sai.addRole(role1.getRname());
}
//通过用户名获取拥有的权限
List<Permission> permission = userService.getPermissionByName(username);
for (Permission permission1 : permission) {
sai.addStringPermission(permission1.getPname());
}
return sai;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取令牌
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//username是肯定相同的 比较密码
String account = teacherService.queryPwdByName(token.getUsername());
if(account != null){
//三个参数(用户名、密码、本realm名字)
return new SimpleAuthenticationInfo(token.getUsername(),account,getName());
}
return null;
}
}
Controller层
@PostMapping("/login")
public String login(String username, String password, Model model){
String pass = new Md5Hash(password).toString();
//创建令牌 将前端传过来的用户名、密码放进令牌
UsernamePasswordToken token = new UsernamePasswordToken(username,pass);
try {
//通过SecurityUtils 获取用户主体
Subject subject = SecurityUtils.getSubject();
//将登录交给SecurityManager进行管理
subject.login(token);
//将信息存入session
// subject.getSession().setAttribute("account",account);
//判断登录的主体是否有user角色
boolean user = subject.hasRole("user");
//判断登录的主题是否有该权限
boolean add = subject.isPermitted("add");
return "index";
} catch (UnknownAccountException e) {
model.addAttribute("msg","用户名错误");
return "login";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg", "密码错误");
return "login";
}
}
认证流程图
授权流程图