1.添加pom
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
2.编写ShiroConfig配置类
@Configuration
public class ShiroConfig {
//注入自定义的realm,告诉shiro如何获取用户信息来做登录或权限控制
@Bean
public Realm realm() {
return new CustomRealm();
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm());
return securityManager;
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置登录应该访问的API
shiroFilterFactoryBean.setLoginUrl("/user/needLogin");
//设置接口访问权限 anon为匿名访问无需登录 authc必须登录
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/login", "anon");
filterMap.put("/user/needLogin", "anon");
filterMap.put("/index_manager/*", "anon");
//除了上面的所有请求需要oauth2认证
filterMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
}
3.编写自定义Realm类
/**
* 这个类主要是自定义了如何查询用户信息,如何查询用户的角色和权限,如何校验密码等逻辑
*/
@Component
public class CustomRealm extends AuthorizingRealm {
@Resource(name = "userServiceImpl")
UserService userService;
//告诉shiro如何根据获取到的用户信息中的密码和盐值来校验密码
{
//设置用于匹配密码的CredentialsMatcher
HashedCredentialsMatcher hashMatcher = new HashedCredentialsMatcher();
hashMatcher.setHashAlgorithmName("md5"); //加密方式 MD5
hashMatcher.setHashIterations(3); //迭代次数 3
this.setCredentialsMatcher(hashMatcher);
}
//定义如何获取用户的角色和权限的逻辑,给shiro做权限判断
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//null usernames are invalid
if (principals == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
}
UserModel user = (UserModel) getAvailablePrincipal(principals);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(user.getRoles());//设置角色
return info;
}
//定义如何获取用户信息的业务逻辑,给shiro做登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
// Null username is invalid
if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm.");
}
UserModel userDB = userService.findUserByUsername(username);
if (userDB == null) {
throw new UnknownAccountException("No account found for admin [" + username + "]");
}
//查询用户的角色和权限存到SimpleAuthenticationInfo中,这样在其它地方
//SecurityUtils.getSubject().getPrincipal()就能拿出用户的所有信息,包括角色和权限
Set<String> roles = userService.getRolesByUsername(userDB.getLoginName());//查询角色信息
if(roles!=null){
userDB.setRoles(roles);
}else {
Set<String> roleTmp = new HashSet<>();
roleTmp.add("normal");//默认普通角色
userDB.setRoles(roleTmp);
}
//第一个参数User类,第二个参数 密码,第三个参数 盐 ,第四个固定 getName()
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDB, userDB.getPassword(),ByteSource.Util.bytes(userDB.getKey()),getName());
return info;
}
}
4.登录接口
@ApiOperation(value = "登录")
@PostMapping("login")
public ApiResp login(@RequestBody @ApiParam(name = "传入username、password",value = "传入json数据类型",required = true) JSONObject jsonObject, HttpSession session){
String username = jsonObject.getString("username");
String password = jsonObject.getString("password");
Subject currentUser = SecurityUtils.getSubject();
currentUser.logout();//避免用户直接返回到登录页登录其他用户,清空缓存
//登录
currentUser.login( new UsernamePasswordToken(username, password) );
//从session取出用户信息
UserModel user = (UserModel) currentUser.getPrincipal();
session.setAttribute("user",user);
if (user==null) throw new AuthenticationException();
//返回登录用户的信息给前台,含用户的所有角色和权限
user.setPassword(null);
user.setKey(null);
return ApiResp.retOK(user);
}
5.设置权限
在方法体前面加上注解
@ApiOperation(value = "分页获取用户列表")
@PostMapping("getUserList")
@RequiresRoles(value={"ss","mdm","mdv"},logical= Logical.OR)
public ApiResp getUserList(){
}
6.注意
前后端分离的项目,前端ajax请求需要增加下面这个才能跨域保存cookie
$.ajax({
xhrFields: {
withCredentials: true
},
....
})