工程结构:
Jar包
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.linzx.test</groupId> <artifactId>test-springshiro</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <org.springframework.version>4.3.3.RELEASE</org.springframework.version> <shiro.version>1.3.2</shiro.version> <junit.version>4.12</junit.version> </properties> <dependencies> <!-- spring mvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> </plugins> </build> </project>
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
Map<String, Filter> filters = new HashMap<>();
filters.put("logout", logoutFilter()); // 退出过滤器
shiroFilter.setFilters(filters);
Map<String, String> 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();
List<String> permissionList = new ArrayList<String>();
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、未登录时访问的提示
登录后访问