SpringBoot整合shiro
在新建的SpringBoot项目中创建config包,新建一个shiro配置类AutuRealm,该类继承AuthorizingRealm,然后重写继承类的两个方法,doGetAuthorizationInfo方法用于用户授权,doGetAuthenticationInfo用于用户认证登录
import com.example.demo.code.Login.permission.Permission;
import com.example.demo.code.Login.role.Role;
import com.example.demo.code.Login.user.User;
import com.example.demo.code.Login.user.UserService;
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 java.util.List;
public class AutuRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 为用户授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取前端输入的用户信息,封装为User对象
User userweb = (User) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//获取前端输入的用户名
String username = userweb.getUsername();
//根据前端输入的用户名查询数据库中对应的记录
User user = userService.findByName((String)principals.getPrimaryPrincipal());
if (user != null){
List<Role> roles = user.getRoles();
for (Role role : roles){
simpleAuthorizationInfo.addRole(role.getRoleName());
List<Permission> permissions = role.getPermissions();
for (Permission permission:permissions){
simpleAuthorizationInfo.addStringPermission(permission.getName());
}
}
}
return simpleAuthorizationInfo;
}
/**
* 认证登录
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//token携带了用户信息
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
//获取前端输入的用户名
String userName = usernamePasswordToken.getUsername();
//根据用户名查询数据库中对应的记录
User user = userService.findByName(userName);
if (user != null){
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
user,//用户
user.getPassword(),//密码
user.getUsername()//real name
);
return simpleAuthenticationInfo;
}
throw new UnknownAccountException();
}
}
然后创建一个Shiro配置类ShiroConfiguration,需要添加Configuration注解
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
/**
* @author
*/
@Configuration
public class ShiroConfiguration {
/**
* 密码校验规则HashedCredentialsMatcher
* 这个类是为了对密码进行编码的 ,
* 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
* 这个类也负责对form里输入的密码进行编码
* 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
*/
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密方式为MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//加密次数
credentialsMatcher.setHashIterations(1024);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
@Bean
public CredentialsMatcher credentialsMatcher() {
return new CredentialsMatcher() {
@Override
public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
return false;
}
};
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(authRealm());
return securityManager;
}
@Bean("authRealm")
public AutuRealm authRealm() {
AutuRealm authRealm = new AutuRealm();
authRealm.setAuthorizationCachingEnabled(false);
authRealm.setCredentialsMatcher(credentialsMatcher());
return authRealm;
}
/**
* 定义shiroFilter过滤器并注入securityManager
* @param
* @return
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置securityManager
bean.setSecurityManager(securityManager);
//设置登录页面
bean.setLoginUrl("login");
//设置登录成功跳转的页面
bean.setSuccessUrl("index");
//设置未授权跳转的页面
bean.setUnauthorizedUrl("unauthorized");
//定义过滤器
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("index", "anon");
filterChainDefinitionMap.put("login", "anon");
filterChainDefinitionMap.put("loginUser", "anon");
filterChainDefinitionMap.put("403","logout");
//需要登录访问的资源 , 一般将/**放在最下边
filterChainDefinitionMap.put("**", "authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}
/**
* Spring的一个bean , 由Advisor决定对哪些类的方法进行AOP代理 .
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
/**
* 配置shiro跟spring的关联
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
return authorizationAttributeSourceAdvisor();
}
/**
* 配置shiro跟spring的关联
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
* lifecycleBeanPostProcessor是负责生命周期的 , 初始化和销毁的类
* (可选)
*/
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
在用户登录时会通过将登录交给shiro处理
@RequestMapping("/loginUser")
public String loginUser(User user, ModelMap model){
try{
String pwd = MD5Util.encrypt(user.getPassword());
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), pwd);
//登录不在该处处理,交由shiro处理
Subject subject = SecurityUtils.getSubject();
subject.login(token);
if (subject.isAuthenticated()) {
return "index";
}else{
model.addAttribute("user",user);
return "index";
}
}catch (IncorrectCredentialsException | UnknownAccountException e) {
model.addAttribute("error", user.getUsername());
e.printStackTrace();
return "login";
} catch(Exception e){
model.addAttribute("user",user);
return "login";
}
}