Apache Shiro 框架(用户登录认证,用户授权和用户注销)

一.简介

 1.  权限框架主要有三种:

① 自己写权限框架
② Spring Security (使用复杂, 依赖 Spring )
Apache Shiro (更轻量, 使用更简单, 并不完全依赖 spring,可以独立使用 )

2.导入jar包(版本1.3.2)

Apache Shiro 框架(用户登录认证,用户授权和用户注销)_第1张图片

二.用户登录功能实现.

1.配置web.xml

代码:

	
	
		
		shiroFilter
		org.springframework.web.filter.DelegatingFilterProxy
	
	
		shiroFilter
		/*
	

2.配置applicationContext-shiro.xml(别忘了在applicationContext.xml中引入)

代码:




	
	
		
		
		
		
		
		
		
		
		
		
			
				/login.html* = anon
				/user_login.action* = anon
				/validatecode.jsp* = anon
				/css/** = anon
				/js/** = anon
				/images/** =anon
				/services/** = anon
				/pages/base/courier.html* = perms[courier:list]
				/pages/base/area.html* = roles[base]
				/** =authc
			
		
	

	
	
		
	
	
	
		
		
	

	
※-->过滤器:

     ①anon 未认证可以访问
     ②authc 认证后可以访问
     ③perms 需要特定权限才能访问
     ④roles 需要特定角色才能访问
     ⑤user 需要特定用户才能访问
     ⑥port 需要特定端口才能访问
     ⑦reset 根据指定 HTTP 请求访问才能访问

     ⑧perms[courier:list]:用于用户权限控制,后面会有写到.

Apache Shiro 框架(用户登录认证,用户授权和用户注销)_第2张图片

3.页面代码.



	
		
		  
		BOS管理系统 登陆页面
		
		
		
	
	
	
		

员工登录

action="user_login.action">
name="username" class="form-control" placeholder="请输入手机号/邮箱/用户名">
name="password" class="form-control" id="inputaccount" placeholder="请输入您的密码">
 记住用户名

地址:北京市昌平区建材城西路金燕龙办公楼一层 邮编:100096 电话:400-618-4000 传真:010-82935100

京ICP备08001421号京公网安备110108007702

注意:红色的"action"的字段在过滤器中是"/user_login.action* = anon",意思就是这个action可以不用认证(没有登录)就可以访问.

4.UserAction提供"login"登录的方法

package cn.itcast.bos.web.action.base.system;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import cn.itcast.bos.system.User;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

@ParentPackage("json-default")
@Namespace("/")
@Controller
@Scope("prototype")
public class UserAction extends ActionSupport implements ModelDriven {

	private User user = new User();

	@Override
	public User getModel() {
		return user;
	}

	@Action(value = "user_login", results = {
			@Result(name = "login", type = "redirect", location = "login.html"),
			@Result(name = "success", type = "redirect", location = "index.html") })
	public String login() {
		//基于Shiro实现登录
		Subject subject = SecurityUtils.getSubject();
		
		//用户名和密码信息
		UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
		
		try {
			subject.login(token);
			//登录成功,将用户信息保存到session当中
			return SUCCESS;
		} catch (AuthenticationException e) {
			//登录失败
			e.printStackTrace();
			return LOGIN;
		}
		
	}
	
	//用户推出登录
	@Action(value="user_logout",results={@Result(name="success",type="redirect",location="login.html")})
	public String logout(){
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return SUCCESS;
	}
}

Shiro 执行流程: 应用程序 --- Subject(action) --- SecurityManager(xml) --- Realm 安全数据

5.自定义Realm对象(实际开发中,只需要继承 AuthorizingRealm )

①将自定义 Realm 注入安全管理器 SecurityManager 当中


	
		
	
②Realm

package cn.itcast.bos.realm;


import java.util.List;

import org.apache.shiro.SecurityUtils;
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.authc.UsernamePasswordToken;
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 org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.itcast.bos.service.base.system.PermissionService;
import cn.itcast.bos.service.base.system.RoleService;
import cn.itcast.bos.service.base.system.Userservice;
import cn.itcast.bos.system.Permission;
import cn.itcast.bos.system.Role;
import cn.itcast.bos.system.User;


// 自定义Realm ,实现安全数据 连接
 @Service("bosRealm")
public class BosRealm extends AuthorizingRealm {

	@Autowired
	private Userservice userService;
	
	@Autowired
	private RoleService roleService;

	@Autowired
	private PermissionService permissionService;


	
	@Override
	// 认证...
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("shiro 认证管理... ");

		// 转换token
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		// 根据用户名 查询 用户信息
		User user = userService.findByUsername(usernamePasswordToken
				.getUsername());
		if (user == null) {
			// 用户名不存在
			// 参数一: 期望登录后,保存在Subject中信息
			// 参数二: 如果返回为null 说明用户不存在,报用户名
			// 参数三 :realm名称
			return null;
		} else {
			// 用户名存在
			// 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致
			// 如果密码一致 登录成功, 如果密码不一致 报密码错误异常
			return new SimpleAuthenticationInfo(user, user.getPassword(),
					getName());
		}

	}
}
红色:错误异常请参考我的博客"最权威正解Submitted credentials for token [xxx]] did not match the expected credentials."这篇文章

③Service和Dao代码

package cn.itcast.bos.service.base.system;

import cn.itcast.bos.system.User;

public interface Userservice {

	public User findByUsername(String username);
}

package cn.itcast.bos.service.base.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.bos.dao.base.system.UserRepository;
import cn.itcast.bos.service.base.system.Userservice;
import cn.itcast.bos.system.User;
@Service
@Transactional
public class UserServiceImpl implements Userservice{

	@Autowired
	private UserRepository userRepository;

	@Override
	public User findByUsername(String username) {
		 return userRepository.findByUsername(username);
	}
	
}

package cn.itcast.bos.dao.base.system;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import cn.itcast.bos.system.User;
@Repository
public interface UserRepository extends JpaRepository{
	public User findByUsername(String username);
}

6.在user表中插入临时用户密码数据,可以校验代码是否正确;

三,用户授权

1.表之间的关系;

Apache Shiro 框架(用户登录认证,用户授权和用户注销)_第3张图片

菜单,权限,角色,用户

①用户:每个用户属于一个角色

Apache Shiro 框架(用户登录认证,用户授权和用户注销)_第4张图片

②每个角色有相应的权限,还有对应的菜单

Apache Shiro 框架(用户登录认证,用户授权和用户注销)_第5张图片

总结:每一位用户都有对应的权限,也有属于自己的菜单列表(动态显示菜单,后面有

2.实现 Realm的授权方法

完整的Realm(包括认证和授权)的代码:

package cn.itcast.bos.realm;


import java.util.List;

import org.apache.shiro.SecurityUtils;
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.authc.UsernamePasswordToken;
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 org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.itcast.bos.service.base.system.PermissionService;
import cn.itcast.bos.service.base.system.RoleService;
import cn.itcast.bos.service.base.system.Userservice;
import cn.itcast.bos.system.Permission;
import cn.itcast.bos.system.Role;
import cn.itcast.bos.system.User;


// 自定义Realm ,实现安全数据 连接
 @Service("bosRealm")
public class BosRealm extends AuthorizingRealm {

	@Autowired
	private Userservice userService;	//用户
	
	@Autowired
	private RoleService roleService;//角色

	@Autowired
	private PermissionService permissionService;//权限名称


	
	@Override
	// 认证...
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("shiro 认证管理... ");

		// 转换token
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		// 根据用户名 查询 用户信息
		User user = userService.findByUsername(usernamePasswordToken
				.getUsername());
		if (user == null) {
			// 用户名不存在
			// 参数一: 期望登录后,保存在Subject中信息
			// 参数二: 如果返回为null 说明用户不存在,报用户名
			// 参数三 :realm名称
			return null;
		} else {
			// 用户名存在
			// 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致
			// 如果密码一致 登录成功, 如果密码不一致 报密码错误异常
			return new SimpleAuthenticationInfo(user, user.getPassword(),
					getName());
		}

	}


	@Override
	// 授权...
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
		System.out.println("shiro 授权管理...");
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		// 根据当前登录用户 查询对应角色和权限
		Subject subject = SecurityUtils.getSubject();
		User user = (User) subject.getPrincipal();
		// 调用业务层,查询角色
		List roles = roleService.findByUser(user);
		for (Role role : roles) {
			authorizationInfo.addRole(role.getKeyword());
		}
		// 调用业务层,查询权限
		List permissions = permissionService.findByUser(user);
		for (Permission permission : permissions) {
			authorizationInfo.addStringPermission(permission.getKeyword());
		}

		return authorizationInfo;
	}
}
授权:将用户对应的权限查询出

博主还没有弄懂查询用户权限之后返回到哪去了!!!知道的小伙请在下面留言,或者去哪个博客下看!

未完待续========================================================!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

你可能感兴趣的:(Dream,Home)