web.xml配置
<!-- shiro filter --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
spring-shiro.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="loginFilter" class="com.aziado.shiro.filter.LoginShiroFilter"/> <bean id="permissionFilter" class="com.aziado.shiro.filter.PermissionShiroFilter"/> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/admin"/> <property name="unauthorizedUrl" value="/admin/index.html?a=1"/> <property name="filterChainDefinitions"> <value> /ltadmin=anon /login/**=anon /admin/**=authc,login,permission </value> </property> <property name="filters"> <map> <entry key="login" value-ref="loginFilter"/> <entry key="permission" value-ref="permissionFilter"/> </map> </property> </bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="shiroRealm"/> </bean> <bean id="shiroRealm" class="com.aziado.shiro.ShiroRealm"></bean> <!-- Shiro生命周期处理器--> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 静态注入,相当于调用SecurityUtils.setSecurityManager(securityManager) --> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/> <property name="arguments" ref="securityManager"/> </bean> </beans>
pom.xml
<dependency> <groupId>net.mingsoft</groupId> <artifactId>shiro-freemarker-tags</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.5</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.5</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.5</version> </dependency>
LoginShiroFilter.java
/** * Created by xucd on 2017/6/6. */ public class LoginShiroFilter extends AccessControlFilter { @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { AdminDo token = TokenManager.getToken(); if(null != token || isLoginRequest(request, response)){// && isEnabled() return Boolean.TRUE; } return Boolean.FALSE ; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //保存Request和Response 到登录后的链接 saveRequestAndRedirectToLogin(request, response); return Boolean.FALSE ; } }
PermissionShiroFilter.java
/** * Created by xucd on 2017/6/6. */ public class PermissionShiroFilter extends AccessControlFilter { @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { //先判断带参数的权限判断 Subject subject = getSubject(request, response); if(null != mappedValue){ String[] arra = (String[])mappedValue; for (String permission : arra) { if(subject.isPermitted(permission)){ return Boolean.TRUE; } } } HttpServletRequest httpRequest = ((HttpServletRequest)request); String uri = httpRequest.getRequestURI();//获取URI String basePath = httpRequest.getContextPath();//获取basePath if(null != uri && uri.startsWith(basePath)){ uri = uri.replace(basePath, ""); } if(subject.isPermitted(uri)){ return Boolean.TRUE; } return Boolean.TRUE; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { Subject subject = getSubject(request, response); if (null == subject.getPrincipal()) { //表示没有登录,重定向到登录页面 saveRequest(request); WebUtils.issueRedirect(request, response, Constants.SHIRO_LOGIN_URL); } else { if (StringUtils.hasText(Constants.SHIRO_UNAUTHORIZED)) { //如果有未授权页面跳转过去 WebUtils.issueRedirect(request, response, Constants.SHIRO_UNAUTHORIZED); } else { //否则返回401未授权状态码 WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED); } } return Boolean.FALSE; } }
TokenManager.java
/** * Created by xucd on 2017/6/6. */ public class TokenManager { /** * 获取当前登录的用户User对象 * @return */ public static AdminDo getToken(){ AdminDo token = new AdminDo(); try { token = (AdminDo) SecurityUtils.getSubject().getPrincipal(); }catch(Exception ex){ ex.printStackTrace(); } return token ; } /** * 获取当前用户的Session * @return */ public static Session getSession(){ return SecurityUtils.getSubject().getSession(); } /** * 把值放入到当前登录用户的Session里 * @param key * @param value */ public static void setVal2Session(Object key ,Object value){ getSession().setAttribute(key, value); } /** * 从当前登录用户的Session里取值 * @param key * @return */ public static Object getVal2Session(Object key){ return getSession().getAttribute(key); } /** * 获取验证码,获取一次后删除 * @return */ public static String getYZM(){ String code = (String) getSession().getAttribute("CODE"); getSession().removeAttribute("CODE"); return code ; } /** * 登录 * @param adminDo * @param rememberMe * @return */ public static AdminDo login(AdminDo adminDo,Boolean rememberMe){ // TODO: 需要调整成密码(第二个参数) ShiroToken token = new ShiroToken(adminDo.getUsername(), adminDo.getUsername()); token.setRememberMe(rememberMe); SecurityUtils.getSubject().login(token); return getToken(); } /** * 判断是否登录 * @return */ public static boolean isLogin() { return null != SecurityUtils.getSubject().getPrincipal(); } /** * 退出登录 */ public static void logout() { SecurityUtils.getSubject().logout(); } }
ShiroRealm.java
/** * Created by xucd on 2017/6/5. */ public class ShiroRealm extends AuthorizingRealm { // @Autowired // UUserService userService; // @Autowired // PermissionService permissionService; // @Autowired // RoleService roleService; @Autowired AdminService adminService; public ShiroRealm() { super(); } /** * 认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken authcToken) throws AuthenticationException { //获取基于用户名和密码的令牌 //实际上这个authcToken是从LoginController里面currentUser.login(session)传过来的 UsernamePasswordToken token = (UsernamePasswordToken)authcToken; System.out.println("MyRealm.doGetAuthenticationInfo.session="+token); // User user = userService.getByUsername(session.getUsername()); // if(null != user){ // AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), user.getNickname()); // this.setSession("currentUser", user); // return authcInfo; // }else{ // return null; // } //此处无需比对,比对的逻辑Shiro会做,我们只需返回一个和令牌相关的正确的验证信息 //说白了就是第一个参数填登录用户名,第二个参数填合法的登录密码(可以是从数据库中取到的,本例中为了演示就硬编码了) //这样一来,在随后的登录页面上就只有这里指定的用户和密码才能通过验证 AdminDo adminDo = new AdminDo(); adminDo.setUsername("xucd"); if("xucd".equals(token.getUsername())){ AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminDo, "xucd", this.getName()); SecurityUtils.getSubject().getSession().setAttribute("currentUser", "xucd"); return authcInfo; }else if("user".equals(token.getUsername())){ AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("user", "user", this.getName()); SecurityUtils.getSubject().getSession().setAttribute("currentUser", "user"); return authcInfo; } //没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常 return null; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { AdminDo adminDo = TokenManager.getToken(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //info.addRole("login"); /* //根据用户ID查询角色(role),放入到Authorization里。 Set<String> roles = new HashSet<String>(); roles.add("login"); //根据用户ID查询权限(permission),放入到Authorization里。 Set<String> permissions = new HashSet<String>(); permissions.add("login:edit"); info.setStringPermissions(permissions); */ return info; } }
ShiroToken.java
/** * Created by xucd on 2017/6/5. */ public class ShiroToken extends UsernamePasswordToken implements java.io.Serializable { private static final long serialVersionUID = -6451794657814516274L; public ShiroToken(String username, String pswd) { super(username, pswd); this.pswd = pswd; } /** * 登录密码[字符串类型] 因为父类是char[] ] **/ private String pswd; public String getPswd() { return pswd; } public void setPswd(String pswd) { this.pswd = pswd; } }