工程结构:
pom.xml
4.0.0 com.linzx.test test-springshiro 0.0.1-SNAPSHOT war UTF-8 1.8 4.3.3.RELEASE 1.3.2 4.12 org.springframework spring-webmvc ${org.springframework.version} org.apache.shiro shiro-core ${shiro.version} org.apache.shiro shiro-spring ${shiro.version} com.fasterxml.jackson.core jackson-databind 2.9.5 javax.servlet javax.servlet-api 4.0.1 provided junit junit ${junit.version} test org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 org.apache.maven.plugins maven-war-plugin 3.2.2
web.xml配置
package com.linzx.test.shiro.config; import javax.servlet.FilterRegistration.Dynamic; import javax.servlet.ServletContext; import javax.servlet.ServletException; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * web.xml * 继承AbstractAnnotationConfigDispatcherServletInitializer,会同时创建DispatcherServlet和ContextLoaderListener */ public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); Dynamic characterEncoding = servletContext.addFilter("characterEncoding", CharacterEncodingFilter.class); characterEncoding.setInitParameter("forceEncoding", "true"); characterEncoding.setInitParameter("encoding", "UTF-8"); characterEncoding.addMappingForUrlPatterns(null, true, "/*"); Dynamic shiroFilter = servletContext.addFilter("shiroFilter", DelegatingFilterProxy.class); shiroFilter.setInitParameter("targetFilterLifecycle", "true"); // 设置true由servlet容器控制filter的生命周期 shiroFilter.addMappingForUrlPatterns(null, true, "/*"); // 静态资源处理 // servletContext.addFilter("resourceUrlEncoding", ResourceUrlEncodingFilter.class).addMappingForUrlPatterns(null, true, "/*"); } }
spring-mvc.xml配置
@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.linzx.test.shiro.controller", includeFilters = @Filter(classes = Controller.class), useDefaultFilters = false) public class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean public SimpleMappingExceptionResolver exceptionResolver() { SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthorized"); mappings.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/unauthenticated"); resolver.setExceptionMappings(mappings); return resolver; } }
shiro.xml配置
package com.linzx.test.shiro.config.security; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.filter.authc.LogoutFilter; 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 com.linzx.test.shiro.security.CustomRealm; @Configuration public class ShiroConfig { @Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { return new AuthorizationAttributeSourceAdvisor(); } /** * 安全管理器 */ @Bean public DefaultWebSecurityManager securityManager() { return new DefaultWebSecurityManager(customRealm()); } /** * 认证、授权 */ @Bean public CustomRealm customRealm() { return new CustomRealm(); } @Bean public ShiroFilterFactoryBean shiroFilter() { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager()); shiroFilter.setLoginUrl("/unauthenticated"); // 未登录跳转url // shiroFilter.setSuccessUrl("/home"); // 登录成功跳转url shiroFilter.setUnauthorizedUrl("/unauthorized"); // 无权限跳转url Mapfilters = new HashMap<>(); filters.put("logout", logoutFilter()); // 退出过滤器 shiroFilter.setFilters(filters); Map filterChainDefinitionMap = new LinkedHashMap<>(); // LinkedHashMap filterChainDefinitionMap.put("/login", "anon"); // 登录接口配置游客权限 filterChainDefinitionMap.put("/logout", "logout"); // 登出接口…… filterChainDefinitionMap.put("/*", "authc"); // 全部接口配置都需要权限 shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilter; } @Bean public LogoutFilter logoutFilter() { return new LogoutFilter(); } }
Realm
package com.linzx.test.shiro.security; import java.util.ArrayList; import java.util.List; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class CustomRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName = (String) principals.getPrimaryPrincipal(); ListpermissionList = new ArrayList (); permissionList.add("user:add"); permissionList.add("user:delete"); if (userName.equals("zhou")) { permissionList.add("user:query"); } SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermissions(permissionList); info.addRole("admin"); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName = (String) token.getPrincipal(); if ("".equals(userName)) { return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, "123456", this.getName()); return info; } }
package com.linzx.test.shiro.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "Hello World!"; } }
package com.linzx.test.shiro.controller; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.linzx.test.shiro.dto.ResultBaseDto; @RestController public class LoginController { @RequestMapping(value = "/login") public ResultBaseDto login(@RequestParam("userName") String userName, @RequestParam("password") String password) { Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, password); try { subject.login(token); } catch (UnknownAccountException e) { e.printStackTrace(); return new ResultBaseDto("001", "用户名或密码错误"); } catch (IncorrectCredentialsException e) { e.printStackTrace(); return new ResultBaseDto("001", "用户名或密码错误"); } return new ResultBaseDto("000"); } }
package com.linzx.test.shiro.controller; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.linzx.test.shiro.dto.ResultBaseDto; @RestController public class CommonController { @RequestMapping("/unauthorized") public ResultBaseDto unauthorized(HttpServletResponse resp) { return new ResultBaseDto("401", "权限不足"); } @RequestMapping("/unauthenticated") public ResultBaseDto unauthenticated(HttpServletResponse resp) { return new ResultBaseDto("403", "未登录"); } }
效果:
1、未登录时访问的提示