1.application.yml
2.pom.xml
3.编写自定义shiro realm
/**
* FileName: MyShiroRealm
* Date: 2018/12/5 15:07:07
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.XXXX.demo.shiro.config;
import com.XXXX.demo.api.vo.RoleVo;
import com.XXXX.demo.api.vo.UserVo;
import com.XXXX.demo.client.core.UserClientService;
import com.XXXX.demo.client.redis.RedisClient;
import com.XXXX.demo.common.pojo.resp.RespMsgBean;
import org.apache.shiro.SecurityUtils;
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 org.springframework.stereotype.Component;
import java.util.*;
/**
* 〈一句话功能简述〉<br>
* 自定义shiro realm
* @create 2018/12/5 15:07:07
* @since 1.0.0
*/
@Component
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private UserClientService userClientService;
@Autowired
private RedisClient redisClient;
@Override
public String getName() {
return "MyShiroRealm";
}
/**
* 身份认证
* @prama
* @return
* @date 2018/12/5 15:40
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("————身份认证方法————");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String name = token.getUsername();
// 先从redis中获取用户信息,从数据库获取对应用户名密码的用户
UserVo user = checkUserFromRedis(name);
if (user.getPassword() == null || user == null) {
throw new AccountException("用户名不正确!");
} else if (!user.getPassword().equals(new String((char[]) token.getCredentials()))) {
throw new AccountException("密码不正确!");
}
return new SimpleAuthenticationInfo(token.getPrincipal(), user.getPassword(), getName());
}
/**
* 权限认证
* @prama
* @return
* @date 2018/12/5 15:40
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// //获取登录用户名
// String name= (String) principalCollection.getPrimaryPrincipal();
// //查询用户名称
// RespMsgBean respMsgBean = userClientService.findByName(name);
// UserVo user = (UserVo) respMsgBean.getData();
// //添加角色和权限
// SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// for (RoleVo role : user.getRoles()) {
// //添加角色
// simpleAuthorizationInfo.addRole(role.getRoleName());
// for (PermissionVo permission:role.getPermissions()) {
// //添加权限
// simpleAuthorizationInfo.addStringPermission(permission.getPermissionName());
// }
// }
// return simpleAuthorizationInfo;
System.out.println("————权限认证————");
String name = (String) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获得该用户角色
UserVo user = checkUserFromRedis(name);
List<RoleVo> roles = user.getRoles();
Set<String> set = new HashSet<>();
//需要将 role 封装到 Set 作为 info.setRoles() 的参数
roles.forEach((role)->{set.add(role.getRoleName());});
//设置该用户拥有的角色
info.setRoles(set);
return info;
}
public UserVo checkUserFromRedis(String name){
UserVo user = null;
Map<String,UserVo> onLineMap = new HashMap<String, UserVo>();
if(!redisClient.hasKeyOfMap("onLineMap",name)){
RespMsgBean<UserVo> respMsgBean = userClientService.findByName(name);
user = respMsgBean.getData();
// 设置缓存
redisClient.setOneMap("onLineMap",name,user,60*60*24*7);
// redisClient.setValue(name,user,60*60*24*7);
}else{
// user = (UserVo) redisClient.getValue(name);
user = (UserVo) redisClient.getValueOfMap("onLineMap",name);
}
return user;
}
}
4.编写shiro配置类,注入相应的bean,此类上一定要加@Configuration注解
/**
* FileName: ShiroConfig
* Date: 2018/12/5 15:00:00
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.XXXX.demo.shiro.config;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 〈一句话功能简述〉<br>
* shiro配置
* @create 2018/12/5 15:00:00
* @since 1.0.0
*/
@Configuration
public class ShiroConfig {
/**
* 将自己的验证方法注入容器
* @prama
* @return
* @date 2018/12/5 15:28
*/
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
/**
* 权限管理,配置主要的realm的管理认证
* @prama
* @return
* @date 2018/12/5 15:30
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm());
return securityManager;
}
/**
* Filter工厂,设置对应的过滤条件和跳转条件
* @prama
* @return
* @date 2018/12/5 16:02
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 登录
shiroFilterFactoryBean.setLoginUrl("/notLogin");
// 设置无权限时跳转的 ur
shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");
// 设置拦截器
Map<String,String> map = new LinkedHashMap<String, String>();
// 普通用户
map.put("/user/**", "roles[user]");
// admin
map.put("/admin/**", "roles[admin]");
// 开放登陆接口
map.put("/login", "anon");
// 登出
// map.put("/logout","logout");
// 对所有用户认证
map.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
System.out.println("Shiro拦截器工厂类注入成功");
return shiroFilterFactoryBean;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
5.编写相应的控制类请求
/**
* FileName: LoginController
* Date: 2018/12/6 15:15:15
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.XXXX.demo.shiro.rest;
import com.XXXX.demo.client.redis.RedisClient;
import com.XXXX.demo.common.pojo.resp.RespMsgBean;
import com.XXXX.demo.shiro.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 〈一句话功能简述〉<br>
* 测试shiro权限
* @create 2018/12/6 15:15:15
* @since 1.0.0
*/
@RestController
public class LoginController {
@Resource
private LoginService loginService;
@RequestMapping(value = "/login", method = RequestMethod.GET)
public RespMsgBean login(String name,String password){
return new RespMsgBean().success(loginService.login(name,password));
}
@RequestMapping(value = "/index", method = RequestMethod.GET)
public RespMsgBean index(){
return new RespMsgBean().success("登陆成功!");
}
@RequestMapping(value = "/notLogin", method = RequestMethod.GET)
public RespMsgBean notLogin() {
return new RespMsgBean().success("您尚未登陆!");
}
@RequestMapping(value = "/notRole", method = RequestMethod.GET)
public RespMsgBean notRole() {
return new RespMsgBean().success("您没有权限!");
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public RespMsgBean logout() {
return new RespMsgBean().success(loginService.logout());
}
}