Apache Shiro是一个强大易用的开源安全框架,用于简化应用程序安全和加强其验证处理,以及控制访问控制行为。Apache Shiro可以做什么?它可以让你编写可维护的安全和认证的实现,特别是工作于常见的web应用和JavaEE的环境,但是它也可以应用于其他 java 环境,如Sevlets、Filter、POJO、JNDI、JavaFX和Spring。
Shiro通过一个FilterChain实施程序过滤,确定请求的URL是否允许访问,以及处理认证和授权,任何一个Filter可以访问身份验证、认证和授权信息。
Shiro有三个核心部件,它们分别是:
-
1.Subject:当前用户身份。
-
2.SecurityManager:它负责协调其他组件
-
3.Realms:我们实际处理认证和授权工作的实体。
方案1
1. 引入下面依赖:
```xml
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.2</version>
</dependency>
```
2. 配置Shiro:
```xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置shiro -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm"/>
</bean>
<bean id="shiroRealm" class="com.example.shiro.ShiroRealm">
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 相关的Filter的配置 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/index" />
<!-- 主要定义静态资源文件未被拦截 -->
<property name="filterChainDefinitions">
<value>
/static/** = anon
/login = anon
/index = anon
/** = user
</value>
</property>
</bean>
</beans>
```
3. 定义Realm:
```java
@Component
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
//认证.登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
String username = utoken.getUsername();
User user = userService.findByUsername(username);
return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码
}
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
return null;
}
}
```
4. 编写Controller:
```java
@RestController
@Controller
public class UserController {
//跳转登录页面
@GetMapping("/login")
public String login(){
return "login";
}
//登录操作
@PostMapping("/login")
public String doLogin(@RequestBody Map<String, String> params){
String userName=params.get("userName");
String password=params.get("password");
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return "index";
} catch (AuthenticationException e) {
//登录失败
}
return "login";
}
}
```
方案二
1、引入依赖:
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
```
2、编写ShiroConfig配置:
```
@Configuration
public class ShiroConfig {
@Bean
public SecurityManager securityManager(Realm myRealm) {
DefaultSecurityManager securityManager = new DefaultSecurityManager(myRealm);
return securityManager;
}
@Bean
public Realm myRealm(HashedCredentialsMatcher credentialsMatcher) {
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher);
return myRealm;
}
@Bean
public FilterRegistrationBean shiroFilterRegistration(SecurityManager securityManager) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.setName("shiroFilter");
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addInitParameter("securityManager", securityManager);
return filterRegistrationBean;
}
@Bean
public HashedCredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("md5");
matcher.setHashIterations(2);
return matcher;
}
@Bean
public DelegatingFilterProxy shiroFilterProxy(SecurityManager securityManager) {
DelegatingFilterProxy filterProxy = new DelegatingFilterProxy("shiroFilter");
filterProxy.setTargetFilterLifecycle(true);
filterProxy.setTargetBeanName("shiroFilter");
return filterProxy;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager);
//未登录的用户请求需要登录的页面时自动跳转到登录页面
bean.setLoginUrl("/login");
//没有权限默认会跳转到的页面
bean.setUnauthorizedUrl("/unauthorizedUrl");
Map<String, String> map = new HashMap<>();
//对静态资源设置匿名访问
map.put("/css/**", "anon");
map.put("/js/**", "anon");
map.put("/layui/**", "anon");
//允许匿名访问
map.put("/user/login", "anon");
//除了匿名访问的资源,其它都要认证
map.put("/**", "authc");
bean.setFilterChainDefinitionMap(map);
return bean;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
}
```
3、自定义Realm;
```
public class MyRealm extends AuthorizingRealm {
@Resource
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取用户信息,获取权限列表
String username = (String) principalCollection.getPrimaryPrincipal();
//获取用户权限
List<String> stringPermissions = userService.findStringPermissionByUsername(username);
info.addStringPermissions(stringPermissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
String password = new String(token.getPassword());
User user = userService.findUserByUsername(username);
if (user != null) {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, user.getPassword(), getName());
return info;
}
return null;
}
}
```
4、自定义Controller, @RequiresAuthentication、@RequiresPermissions
```
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/unauthorizedUrl")
public String unauthorized() {
return "unauthorizedUrl";
}
@GetMapping("/index")
@RequiresAuthentication
public String index(){
return "index";
}
@GetMapping("/admin")
@RequiresPermissions("admin")
public String admin(){
return "admin";
}
}
```
5、启动类,添加@EnableWebSecurity注解进行注册
```
@SpringBootApplication
@EnableWebSecurity
public class SimpleAppApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleAppApplication.class, args);
}
}
```
文章评论