pom文件导入
org.apache.shiro
shiro-core
1.4.0
org.apache.shiro
shiro-spring
1.4.0
org.apache.shiro
shiro-ehcache
1.4.0
org.apache.shiro
shiro-web
1.4.0
Shiro权限配置主类
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 描述:Shiro权限配置
*/
@Configuration
public class ShiroConfig {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
*
Filter Chain定义说明
1、一个URL可以配置多个Filter,使用逗号分隔
2、当设置多个过滤器时,全部验证通过,才视为通过
3、部分过滤器可指定参数,如perms,roles
*
*/
@Bean
public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager manager){
System.out.println(" 。。。。shirFilter。。。。。。 ");
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
// 配置登录的url和登录成功的url
// bean.setLoginUrl("/static/html/login.html");
// bean.setSuccessUrl("/home");
// 定义过滤器
Map filterMap = new LinkedHashMap<>();
filterMap.put("authc", new ShiroLoginFilter());
filterMap.put("perms", new ShiroPermissionsFilter());
bean.setFilters(filterMap);
// 配置访问权限
LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不同的URL采用的验证方式
// anon表示可以匿名访问
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/info", "authc,perms");// 表示需要认证才可以访问
// filterChainDefinitionMap.put("/**", "authc,perms");// 表示需要认证才可以访问
// filterChainDefinitionMap.put("/*.*", "authc,perms");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}
// 配置核心安全事务管理器
@Bean(name = "securityManager")
public SecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm) {
System.err.println("--------------shiro已经加载----------------");
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(userRealm);
// manager.setSessionManager(sessionManager);
// manager.setCacheManager();
return manager;
}
// 配置自定义的权限登录器
@Bean(name = "userRealm")
public UserRealm userRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(matcher);
return userRealm;
}
// 配置自定义的密码匹配比较器
@Bean(name = "credentialsMatcher")
public CredentialsMatcher credentialsMatcher() {
return new CredentialsMatcher();
}
}
密码匹配
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
/**
*
* 描述:密码匹配比较
*/
public class CredentialsMatcher extends SimpleCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
System.out.println("....密码的比对....");
UsernamePasswordToken utoken = (UsernamePasswordToken) token;
// 获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
String inPassword = new String(utoken.getPassword());
// 获得数据库中的密码
String dbPassword = (String) info.getCredentials();
// 进行密码的比对
return this.equals(inPassword, dbPassword);
}
}
用户
/**
* 描述:用户
*/
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
登录及授权
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 java.util.ArrayList;
import java.util.List;
/**
*
* 描述:登录及授权
*/
public class UserRealm extends AuthorizingRealm {
// 认证.登录 提供账户信息返回认证信息
/**
* 当调用如下代码时会进入这个方法(一般是登录页面)
* Subject currentUser = SecurityUtils.getSubject();
* currentUser.login(token);
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
UsernamePasswordToken utoken = (UsernamePasswordToken) authenticationToken; // 获取用户输入的token
System.out.println(".....认证.登录....");
//根据用户名去数据库查询相关记录,并返回验证
String username = utoken.getUsername();
//
User user = new User();
user.setUsername(username);
user.setPassword("123456");
if (user == null) {
return null;
}
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
}
// 授权 角色
// 提供用户信息返回权限信息
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取session中的用户
User user = (User) principalCollection.fromRealm(this.getClass().getName()).iterator().next();
System.out.println();
System.out.println(".....授权....");
System.out.println();
List permissions = new ArrayList<>();
permissions.add("abc1");
permissions.add("abc2");
// Set roles = user.getRoles();
// for (Role role : roles) {
// Set modules = role.getModules();
// for (Module module : modules) {
// permissions.add(module.getCode());
// }
// }
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions); // 将权限放入shiro中.
return info;
}
}
判断是否已经登录
import org.apache.shiro.web.servlet.AdviceFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 判断是否登录的过滤器,被Shiro组件调用使用
*/
public class ShiroLoginFilter extends AdviceFilter {
/**
* 在访问controller前判断是否登录,返回json,不进行重定向。
*
* @param request
* @param response
* @return true-通过验证,false-验证失败
* @throws Exception
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
User User = (User) httpServletRequest.getSession().getAttribute("user");
httpServletRequest.getSession().setMaxInactiveInterval(36000);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json");
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with");
PrintWriter printWriter = null;
if (null == User) {
try {
printWriter = response.getWriter();
printWriter.write("{\"errorCode\": \"未登录\"}");
printWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (printWriter != null) {
printWriter.close();
}
}
return false;
}
return true;
}
}
判断是否有权限
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
*
* 描述:验证是否有权限的过滤器
*/
public class ShiroPermissionsFilter extends PermissionsAuthorizationFilter {
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
// 记录日志
Subject subject = this.getSubject(request, response);
/**获取用户信息,可以根据用户信息查看有没有对应模块的权限*/
User user = (User) subject.getPrincipal();
//true有权限; false没有权限
boolean isPermitted = false;
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String code = httpServletRequest.getParameter("cmd");
//写死一个权限作为测试
if(code.equals("100"))//如何cmd=100就有权限
isPermitted = true;
return isPermitted;
}
/**
* shiro认证perms资源失败后回调方法
*
* @param servletRequest
* @param servletResponse
* @return
* @throws IOException
*/
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {
PrintWriter printWriter = null;
try {
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("application/json");
printWriter = servletResponse.getWriter();
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
printWriter.write("{\"error\": \"没有权限\"}");
printWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (printWriter != null) {
printWriter.close();
}
}
return false;
}
}
Controller
import com.szcentral.conf.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
* Created by cgz on 2018-04-08 14:11
* 描述:
*/
@RestController
public class SampleController {
@RequestMapping("/")
String home() {
return "Hello World!";
}
@RequestMapping("/info")
public Map getMap(){
Map map = new HashMap();
map.put("name", "chen");
map.put("age", "22");
map.put("tel", "13682452210");
return map;
}
@RequestMapping("/login")
public String login(HttpSession session,
HttpServletRequest request,
HttpServletResponse response){
System.out.println("...接收登录Controller。。。。");
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
String username = "chen";
String pwd = "123456";
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, pwd);
//进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
User user = (User) subject.getPrincipal();
session.setAttribute("user", user);
return "login";
}
}