当前位置: 首页 > 工具软件 > jfinal-admin > 使用案例 >

JFinal-shiro-oAuth

呼延才
2023-12-01



记录下来一遍以后回顾.

先推荐几个参考项目 


https://github.com/Dreampie/jfinal-shiro

http://www.oschina.net/code/snippet_96568_33628

几个主要的文件


Maven pom.xml

<dependency>
			<groupId>org.apache.oltu.oauth2</groupId>
			<artifactId>org.apache.oltu.oauth2.authzserver</artifactId>
			<version>0.31</version>
		</dependency>

		<dependency>
			<groupId>org.apache.oltu.oauth2</groupId>
			<artifactId>org.apache.oltu.oauth2.resourceserver</artifactId>
			<version>0.31</version>
		</dependency>
		
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.3</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>1.2.2</version>
		</dependency>
		
		<dependency>
		   <groupId>cn.dreampie</groupId>
		   <artifactId>jfinal-shiro</artifactId>
		   <version>0.2</version>
		</dependency>




客户端

public class IndexController extends Controller {

	public void index() {
		if (null == getPara("code", null)) {
			redirect(ClientRes.getString(ClientRes.LOGIN_URL));
			return;
		}

		try {
			// 认证服务器返回授权码,根据授权码,客户端ID,客户端密匙,组装OAuthClientRequest,前往服务端获取访问令牌
			OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
			OAuthClientRequest accessTokenRequest = OAuthClientRequest
					.tokenLocation(
							ClientRes.getString(ClientRes.ACCESS_TOKEN_URL))
					.setGrantType(GrantType.AUTHORIZATION_CODE)
					.setClientId(ClientRes.getString(ClientRes.CLIENT_ID))
					.setClientSecret(
							ClientRes.getString(ClientRes.CLIENT_SECRET))
					.setCode(getPara("code"))
					.setRedirectURI(ClientRes.getString(ClientRes.REDIRECT_URL))
					.buildQueryMessage();
			OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(
					accessTokenRequest, OAuth.HttpMethod.POST);
			String accessToken = oAuthResponse.getAccessToken();
			// Long expiresIn = oAuthResponse.getExpiresIn();
			// 根据访问令牌去资源服务器获取数据
			OAuthClientRequest resourceRequest = new OAuthBearerClientRequest(
					ClientRes.getString(ClientRes.RESOURCE_URL))
					.setAccessToken(accessToken).buildQueryMessage();
			OAuthResourceResponse resourceResponse = oAuthClient.resource(
					resourceRequest, OAuth.HttpMethod.GET,
					OAuthResourceResponse.class);
			String username = resourceResponse.getBody();

			System.out.println(username);
			render(new JsonRender(username).forIE());

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

配置文件

CLIENT_ID = c1ebe466-1cdc-4bd3-ab69-77c3561b9dee
CLIENT_SECRET = d8346ea2-6017-43ed-ad68-19c0f971738b
ACCESS_TOKEN_URL = http://localhost:8443/accessToken
RESOURCE_URL = http://localhost:8443/resource
REDIRECT_URL = http://localhost:90
#LOGIN_URL = http://localhost:8443/authorize?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee&response_type=code&redirect_uri=http://localhost:90
LOGIN_URL = http://localhost:8443/authorize?client_id=c1ebe466-1cdc-4bd3-ab69-77c3561b9dee&response_type=code&username=admin&redirect_uri=http://localhost:90



认证服务器

public class AuthorizeController extends Controller {

	private static OAuthService oAuthService = new OAuthServiceImpl(
			CacheKit.getCacheManager());

	public void index() throws OAuthSystemException {

		try {
			// 构建OAuth授权请求
			OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(getRequest());

			// 检查传入的客户端id是否正确
			if (!oAuthService.checkClientId(oauthRequest.getClientId())) {
				OAuthResponse response = OAuthASResponse
						.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
						.setError(OAuthError.TokenResponse.INVALID_CLIENT)
						.setErrorDescription(
								Constants.INVALID_CLIENT_DESCRIPTION)
						.buildJSONMessage();
				render(new JsonRender("{\"result\":0,\"msg\":\"客户端id错误!\"}")
						.forIE());
				return;
			}

			Subject subject = SecurityUtils.getSubject();

			// 如果用户没有登录,跳转到登陆页面
			if (!subject.isAuthenticated()) {
				if (!login(subject)) {// 登录失败时跳转到登陆页面
					render(new JsonRender(
							"{\"result\":0,\"msg\":\"用户未登录,请先登录授权!\"}").forIE());
					return;
				}
			}

			User user = (User) subject.getPrincipal();

			// User user = User.dao.findById(1);

			// 生成授权码
			String authorizationCode = null;
			// responseType目前仅支持CODE,另外还有TOKEN
			String responseType = oauthRequest
					.getParam(OAuth.OAUTH_RESPONSE_TYPE);
			if (responseType.equals(ResponseType.CODE.toString())) {
				OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(
						new MD5Generator());
				authorizationCode = oauthIssuerImpl.authorizationCode();
				oAuthService.addAuthCode(authorizationCode,
						user.getStr("username"));
			}

			// 进行OAuth响应构建
			OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse
					.authorizationResponse(getRequest(),
							HttpServletResponse.SC_FOUND);
			// 设置授权码
			builder.setCode(authorizationCode);
			// 得到到客户端重定向地址
			String redirectURI = oauthRequest
					.getParam(OAuth.OAUTH_REDIRECT_URI);

			// 构建响应
			final OAuthResponse response = builder.location(redirectURI)
					.buildQueryMessage();

			redirect(response.getLocationUri(), true);
		} catch (OAuthProblemException e) {
			// 出错处理
			String redirectUri = e.getRedirectUri();
			if (OAuthUtils.isEmpty(redirectUri)) {
				// 告诉客户端没有传入redirectUri直接报错
				render(new JsonRender(
						"OAuth callback url needs to be provided by client!!!",
						401).forIE());
			}

			// 返回错误消息(如?error=)
			final OAuthResponse response = OAuthASResponse
					.errorResponse(HttpServletResponse.SC_FOUND).error(e)
					.location(redirectUri).buildQueryMessage();

			redirect(response.getLocationUri(), true);
		}
	}

	private boolean login(Subject subject) {
		try {
			String username = getPara("username", "");
			String password = getPara("password", "admin");
			if ("".equals(username) || "".equals(password)) {
				return false;
			}
			UsernamePasswordToken token = new UsernamePasswordToken(username,
					password);
			subject.login(token);
			return true;
		} catch (UnknownAccountException uae) {
			System.out.println("账户不存在!");
		} catch (IncorrectCredentialsException ice) {
			System.out.println("密码不正确!");
		} catch (LockedAccountException lae) {
			System.out.println("账户被禁了!");
		} catch (AuthenticationException ae) {
			System.out.println("认证错误!");
		}
		return false;
	}
}

public class AccessTokenController extends Controller {

	private static OAuthService oAuthService = new OAuthServiceImpl(
			CacheKit.getCacheManager());

	public void index() throws URISyntaxException, OAuthSystemException {

		try {
			// 构建OAuth请求
			OAuthTokenRequest oauthRequest = new OAuthTokenRequest(getRequest());

			// 检查提交的客户端id是否正确
			if (!oAuthService.checkClientId(oauthRequest.getClientId())) {
				OAuthResponse response = OAuthASResponse
						.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
						.setError(OAuthError.TokenResponse.INVALID_CLIENT)
						.setErrorDescription(
								Constants.INVALID_CLIENT_DESCRIPTION)
						.buildJSONMessage();
				render(new JsonRender(response).forIE());
				return;
			}

			// 检查客户端安全KEY是否正确
			if (!oAuthService.checkClientSecret(oauthRequest.getClientSecret())) {
				OAuthResponse response = OAuthASResponse
						.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
						.setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
						.setErrorDescription(
								Constants.INVALID_CLIENT_DESCRIPTION)
						.buildJSONMessage();
				render(new JsonRender(response).forIE());
				return;
			}

			String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE);
			// 检查验证类型,此处只检查AUTHORIZATION_CODE类型,其他的还有PASSWORD或REFRESH_TOKEN
			if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(
					GrantType.AUTHORIZATION_CODE.toString())) {
				if (!oAuthService.checkAuthCode(authCode)) {
					OAuthResponse response = OAuthASResponse
							.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
							.setError(OAuthError.TokenResponse.INVALID_GRANT)
							.setErrorDescription("错误的授权码").buildJSONMessage();
					render(new JsonRender(response).forIE());
					return;
				}
			}

			// 生成Access Token
			OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(
					new MD5Generator());
			final String accessToken = oauthIssuerImpl.accessToken();
			oAuthService.addAccessToken(accessToken,
					oAuthService.getUsernameByAuthCode(authCode));

			// 生成OAuth响应
			OAuthResponse response = OAuthASResponse
					.tokenResponse(HttpServletResponse.SC_OK)
					.setAccessToken(accessToken)
					.setExpiresIn(String.valueOf(oAuthService.getExpireIn()))
					.buildJSONMessage();

			// 根据OAuthResponse生成ResponseEntity
			render(new JsonRender(response.getBody()).forIE());

		} catch (OAuthProblemException e) {
			// 构建错误响应
			OAuthResponse response = OAuthASResponse
					.errorResponse(HttpServletResponse.SC_BAD_REQUEST).error(e)
					.buildJSONMessage();
			render(new JsonRender(response).forIE());
		}
	}

}

资源服务器

public class ResourceController extends Controller {

	private static OAuthService oAuthService = new OAuthServiceImpl(
			CacheKit.getCacheManager());

	public void index() throws OAuthSystemException {

		try {
			// 构建OAuth资源请求
			OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(
					getRequest(), ParameterStyle.QUERY);
			// 获取Access Token
			String accessToken = oauthRequest.getAccessToken();

			// 验证Access Token
			if (!oAuthService.checkAccessToken(accessToken)) {
				// 如果不存在/过期了,返回未验证错误,需重新验证
				OAuthResponse response = OAuthRSResponse
						.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
						.setRealm(Constants.RESOURCE_SERVER_NAME)
						.setError(OAuthError.ResourceResponse.INVALID_TOKEN)
						.buildHeaderMessage();
				render(new JsonRender(response).forIE());
				return;
			}

			// 返回用户名
			String username = oAuthService
					.getUsernameByAccessToken(accessToken);
			render(new JsonRender(username).forIE());
		} catch (OAuthProblemException e) {
			// 检查是否设置了错误码
			String errorCode = e.getError();
			if (OAuthUtils.isEmpty(errorCode)) {
				OAuthResponse response = OAuthRSResponse
						.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
						.setRealm(Constants.RESOURCE_SERVER_NAME)
						.buildHeaderMessage();
				render(new JsonRender(response).forIE());
			}

			OAuthResponse response = OAuthRSResponse
					.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
					.setRealm(Constants.RESOURCE_SERVER_NAME)
					.setError(e.getError())
					.setErrorDescription(e.getDescription())
					.setErrorUri(e.getUri()).buildHeaderMessage();
			render(new JsonRender(response).forIE());
		}
	}
}

缓存

<ehcache name="shiro">

	<diskStore path="java.io.tmpdir/shiro-ehcache" />



	<defaultCache maxElementsInMemory="1000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
		diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
		diskSpoolBufferSizeMB="50" />


	<!-- 登录记录缓存 锁定10分钟 -->
	<cache name="passwordRetryCache" maxEntriesLocalHeap="2000"
		eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
		overflowToDisk="false" statistics="true">
	</cache>

	<cache name="authorizationCache" maxEntriesLocalHeap="2000"
		eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
		overflowToDisk="false" statistics="true">
	</cache>

	<cache name="authenticationCache" maxEntriesLocalHeap="2000"
		eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
		overflowToDisk="false" statistics="true">
	</cache>

	<cache name="shiro-activeSessionCache" maxEntriesLocalHeap="2000"
		eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
		overflowToDisk="false" statistics="true">
	</cache>

	<cache name="code-cache" maxEntriesLocalHeap="2000" eternal="false"
		timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
		statistics="true">
	</cache>

</ehcache>


shiro配置文件

[main]

authc = cn.dreampie.shiro.ShiroFormAuthenticationFilter
authc.useCaptcha = false
#默认登陆数据提交路径
authc.loginUrl = /signin
#分角色登录提交配置
#authc.loginUrlMap = R_ADMIN:/admin/signin
#默认或者successUrlMap没有该角色时
authc.successUrl = /order
#不同角色登陆到不同的url,R_USER:/order可以不配置,会默认使用successUrl
authc.successUrlMap = R_USER:/order,R_MEMBER:/order/region,R_MANAGER:/order/branch,R_ADMIN:/order/branch
authc.failureUrl = /
#不同角色登陆失败跳转的路径
#authc.failureUrlMap =R_ADMIN:/admin/login

signout = cn.dreampie.shiro.ShiroLogoutFilter
#默认的退出url,redirectUrlMap里没有该角色使用该url
signout.redirectUrl = /
#如果你要区分不同角色推出到不同的url,使用map
#signout.redirectUrlMap = R_ADMIN:/admin/index

#realm
myRealm = com.tbynet.sooeso.realm.ShiroDbRealm
securityManager.realm = $myRealm

passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = cn.dreampie.shiro.ShiroPasswordMatcher
passwordMatcher.passwordService = $passwordService
myRealm.credentialsMatcher = $passwordMatcher

#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache-shiro.xml
securityManager.cacheManager = $shiroCacheManager

#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO.activeSessionsCacheName = shiro-activeSessionCache
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
sessionListener = cn.dreampie.shiro.listeners.ShiroSessionListener
securityManager.sessionManager.sessionListeners = $sessionListener

securityManager.sessionManager.globalSessionTimeout = 1200000
securityManager.sessionManager.sessionValidationSchedulerEnabled = false
securityManager.sessionManager.deleteInvalidSessions = false



[urls]  
/** = anon

/authorize/**=anon
/accessToken/**=anon
/userInfo/**=anon

数据库

/*
SQLyog v10.2 
MySQL - 5.5.40 : Database - oauth2
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`oauth2` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `oauth2`;

/*Table structure for table `oauth2_client` */

DROP TABLE IF EXISTS `oauth2_client`;

CREATE TABLE `oauth2_client` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `client_name` varchar(100) DEFAULT NULL,
  `client_id` varchar(100) DEFAULT NULL,
  `client_secret` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_oauth2_client_client_id` (`client_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

/*Data for the table `oauth2_client` */

insert  into `oauth2_client`(`id`,`client_name`,`client_id`,`client_secret`) values (1,'chapter17-client','c1ebe466-1cdc-4bd3-ab69-77c3561b9dee','d8346ea2-6017-43ed-ad68-19c0f971738b');

/*Table structure for table `oauth2_user` */

DROP TABLE IF EXISTS `oauth2_user`;

CREATE TABLE `oauth2_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_oauth2_user_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

/*Data for the table `oauth2_user` */

insert  into `oauth2_user`(`id`,`username`,`password`,`salt`) values (1,'admin','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f');

/*Table structure for table `sec_permission` */

DROP TABLE IF EXISTS `sec_permission`;

CREATE TABLE `sec_permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '名称',
  `value` varchar(50) NOT NULL COMMENT '值',
  `url` varchar(255) DEFAULT NULL COMMENT 'url地址',
  `intro` varchar(255) DEFAULT NULL COMMENT '简介',
  `pid` bigint(20) DEFAULT '0' COMMENT '父级id',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='权限';

/*Data for the table `sec_permission` */

insert  into `sec_permission`(`id`,`name`,`value`,`url`,`intro`,`pid`,`created_at`,`updated_at`,`deleted_at`) values (1,'管理员目录','P_D_ADMIN','/admin/**','',0,'2015-05-07 16:44:40',NULL,NULL),(2,'角色权限管理','P_ROLE','/admin/role/**','',1,'2015-05-07 16:44:40',NULL,NULL),(3,'用户管理','P_USER','/admin/user/**','',1,'2015-05-07 16:44:40',NULL,NULL),(4,'总部目录','P_D_MEMBER','/member/**','',0,'2015-05-07 16:44:40',NULL,NULL),(5,'分部目录','P_D_USER','/user/**','',0,'2015-05-07 16:44:40',NULL,NULL),(6,'用户处理','P_USER_CONTROL','/user/branch**','',5,'2015-05-07 16:44:40',NULL,NULL),(7,'订单','P_ORDER','/order/**','',0,'2015-05-07 16:44:40',NULL,NULL),(8,'订单处理','P_ORDER_CONTROL','/order/deliver**','',7,'2015-05-07 16:44:40',NULL,NULL),(9,'订单更新','P_ORDER_UPDATE','/order/update**','',7,'2015-05-07 16:44:40',NULL,NULL),(10,'支部订单','P_ORDER_BRANCH','/order/branch**','',7,'2015-05-07 16:44:40',NULL,NULL),(11,'区域支行处理','P_REGION_CONTROL','/order/region**','',7,'2015-05-07 16:44:40',NULL,NULL),(12,'收货地址','P_Address','/address/**','',0,'2015-05-07 16:44:40',NULL,NULL);

/*Table structure for table `sec_role` */

DROP TABLE IF EXISTS `sec_role`;

CREATE TABLE `sec_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '名称',
  `value` varchar(50) NOT NULL COMMENT '值',
  `intro` varchar(255) DEFAULT NULL COMMENT '简介',
  `pid` bigint(20) DEFAULT '0' COMMENT '父级id',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='角色';

/*Data for the table `sec_role` */

insert  into `sec_role`(`id`,`name`,`value`,`intro`,`pid`,`created_at`,`updated_at`,`deleted_at`) values (1,'超级管理员','R_ADMIN','',0,'2015-05-07 16:44:40',NULL,NULL),(2,'系统管理员','R_MANAGER','',1,'2015-05-07 16:44:40',NULL,NULL),(3,'总部','R_MEMBER','',2,'2015-05-07 16:44:40',NULL,NULL),(4,'分部','R_USER','',2,'2015-05-07 16:44:40',NULL,NULL);

/*Table structure for table `sec_role_permission` */

DROP TABLE IF EXISTS `sec_role_permission`;

CREATE TABLE `sec_role_permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `role_id` bigint(20) NOT NULL,
  `permission_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 COMMENT='角色权限';

/*Data for the table `sec_role_permission` */

insert  into `sec_role_permission`(`id`,`role_id`,`permission_id`) values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,1,5),(6,1,6),(7,1,7),(8,1,8),(9,1,9),(10,1,10),(11,1,11),(12,1,12),(13,2,1),(14,2,3),(15,2,4),(16,2,5),(17,2,6),(18,2,7),(19,2,8),(20,2,9),(21,2,10),(22,2,11),(23,2,12),(24,3,4),(25,3,5),(26,3,6),(27,3,11),(28,4,5),(29,4,7),(30,4,9),(31,4,12);

/*Table structure for table `sec_user` */

DROP TABLE IF EXISTS `sec_user`;

CREATE TABLE `sec_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '登录名',
  `providername` varchar(50) NOT NULL COMMENT '提供者',
  `email` varchar(200) DEFAULT NULL COMMENT '邮箱',
  `phone` varchar(50) DEFAULT NULL COMMENT '联系电话',
  `password` varchar(200) NOT NULL COMMENT '密码',
  `hasher` varchar(200) NOT NULL COMMENT '加密类型',
  `salt` varchar(200) NOT NULL COMMENT '加密盐',
  `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像',
  `first_name` varchar(10) DEFAULT NULL COMMENT '名字',
  `last_name` varchar(10) DEFAULT NULL COMMENT '姓氏',
  `full_name` varchar(20) DEFAULT NULL COMMENT '全名',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户';

/*Data for the table `sec_user` */

insert  into `sec_user`(`id`,`username`,`providername`,`email`,`phone`,`password`,`hasher`,`salt`,`avatar_url`,`first_name`,`last_name`,`full_name`,`created_at`,`updated_at`,`deleted_at`) values (1,'admin','shengmu','wangrenhui1990@gmail.com','15611434500','$shiro1$SHA-256$500000$OBABsRNo28z7O839AycvrQ==$yn8q8rQ0siF5Leie0YyNax4w6upzkKNVQt2bfprGx8I=','default_hasher','','','管理员','圣牧','圣牧.管理员','2015-05-07 16:44:41',NULL,NULL);

/*Table structure for table `sec_user_info` */

DROP TABLE IF EXISTS `sec_user_info`;

CREATE TABLE `sec_user_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `creator_id` bigint(20) DEFAULT NULL COMMENT '创建者id',
  `gender` int(11) DEFAULT '0' COMMENT '性别0男,1女',
  `province_id` bigint(20) DEFAULT NULL COMMENT '省id',
  `city_id` bigint(20) DEFAULT NULL COMMENT '市id',
  `county_id` bigint(20) DEFAULT NULL COMMENT '县id',
  `street` varchar(500) DEFAULT NULL COMMENT '街道',
  `zip_code` varchar(50) DEFAULT NULL COMMENT '邮编',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户信息';

/*Data for the table `sec_user_info` */

insert  into `sec_user_info`(`id`,`user_id`,`creator_id`,`gender`,`province_id`,`city_id`,`county_id`,`street`,`zip_code`,`created_at`,`updated_at`,`deleted_at`) values (1,1,0,0,1,2,3,'人民大学',NULL,'2015-05-07 16:44:41',NULL,NULL);

/*Table structure for table `sec_user_role` */

DROP TABLE IF EXISTS `sec_user_role`;

CREATE TABLE `sec_user_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `role_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户角色';

/*Data for the table `sec_user_role` */

insert  into `sec_user_role`(`id`,`user_id`,`role_id`) values (1,1,1);

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;


ShiroDbAuthzService
public class ShiroDbAuthzService implements JdbcAuthzService {

	@Override
	public Map<String, AuthzHandler> getJdbcAuthz() {
		// 加载数据库的url配置
		// 按长度倒序排列url
		Map<String, AuthzHandler> authzJdbcMaps = Collections
				.synchronizedMap(new TreeMap<String, AuthzHandler>(
						new Comparator<String>() {
							public int compare(String k1, String k2) {
								int result = k2.length() - k1.length();
								if (result == 0) {
									return k1.compareTo(k2);
								}
								return result;
							}
						}));
		
		// 遍历角色
		List<Role> roles = Role.dao.find("select * from sec_role");
		List<Permission> permissions = null;
		for (Role role : roles) {
			// 角色可用
			if (role.getDate("daleted_at") == null) {
				permissions = Permission.dao.findByRoleId(role.get("id"));
				// 遍历权限
				for (Permission permission : permissions) {
					// 权限可用
					if (permission.getDate("daleted_at") == null) {
						if (permission.getStr("url") != null
								&& !permission.getStr("url").isEmpty()) {
							authzJdbcMaps.put(
									permission.getStr("url"),
									new JdbcPermissionAuthzHandler(permission
											.getStr("value")));
						}
					}
				}
			}
		}
		return authzJdbcMaps;
	}
}


ShiroDbRealm
public class ShiroDbRealm extends AuthorizingRealm {

	/**
	 * 登录认证
	 * 
	 * @param token
	 * @return
	 * @throws org.apache.shiro.authc.AuthenticationException
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken userToken = (UsernamePasswordToken) token;
		User user = null;
		String username = userToken.getUsername();
		if (ValidateKit.isEmail(username)) {
			user = User.dao
					.findFirst(
							"SELECT id,username,providername,email,phone,password,hasher,salt,avatar_url,first_name,last_name,full_name,created_at,updated_at,deleted_at FROM sec_user  WHERE email=? AND  deleted_at IS NULL",
							username);
		} else if (ValidateKit.isMobile(username)) {
			user = User.dao
					.findFirst(
							"SELECT id,username,providername,email,phone,password,hasher,salt,avatar_url,first_name,last_name,full_name,created_at,updated_at,deleted_at FROM sec_user  WHERE phone=? AND  deleted_at IS NULL",
							username);
		} else {
			user = User.dao
					.findFirst(
							"SELECT id,username,providername,email,phone,password,hasher,salt,avatar_url,first_name,last_name,full_name,created_at,updated_at,deleted_at FROM sec_user  WHERE username=? AND  deleted_at IS NULL",
							username);
		}
		if (user != null) {
			SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,
					user.getStr("password"), getName());
			return info;
		} else {
			return null;
		}
	}

	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 * 
	 * @param principals
	 *            用户信息
	 * @return
	 */
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		String loginName = ((User) principals.fromRealm(getName()).iterator()
				.next()).get("username");
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		Set<String> roleSet = new LinkedHashSet<String>(); // 角色集合
		Set<String> permissionSet = new LinkedHashSet<String>(); // 权限集合
		List<Role> roles = null;
		User user = User.dao
				.findFirst(
						"SELECT id,username,providername,email,phone,PASSWORD,hasher,salt,avatar_url,first_name,last_name,full_name,created_at,updated_at,deleted_at FROM sec_user  WHERE username=? AND  deleted_at IS NULL",
						loginName);
		if (user != null) {
			// 遍历角色
			roles = Role.dao.findByUserId(user.getLong("id"));
		} else {
			SubjectKit.getSubject().logout();
		}

		loadRole(roleSet, permissionSet, roles);
		info.setRoles(roleSet); // 设置角色
		info.setStringPermissions(permissionSet); // 设置权限
		return info;
	}

	/**
	 * @param roleSet
	 * @param permissionSet
	 * @param roles
	 */
	private void loadRole(Set<String> roleSet, Set<String> permissionSet,
			List<Role> roles) {
		List<Permission> permissions;
		for (Role role : roles) {
			// 角色可用
			if (role.getDate("deleted_at") == null) {
				roleSet.add(role.getStr("value"));
				permissions = Permission.dao.findByRoleId(role.getLong("id"));
				loadAuth(permissionSet, permissions);
			}
		}
	}

	/**
	 * @param permissionSet
	 * @param permissions
	 */
	private void loadAuth(Set<String> permissionSet,
			List<Permission> permissions) {
		// 遍历权限
		for (Permission permission : permissions) {
			// 权限可用
			if (permission.getDate("deleted_at") == null) {
				permissionSet.add(permission.getStr("value"));
			}
		}
	}

	/**
	 * 更新用户授权信息缓存.
	 */

	public void clearCachedAuthorizationInfo(Object principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(
				principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if (cache != null) {
			for (Object key : cache.keys()) {
				cache.remove(key);
			}
		}
	}
}


  

</pre>记录下来一遍以后回顾.<p></p><p></p><p>先推荐几个参考项目 </p><p><a target=_blank target="_blank" href="https://github.com/Dreampie/jfinal-shiro">https://github.com/Dreampie/jfinal-shiro</a></p><p><a target=_blank target="_blank" href="http://www.oschina.net/code/snippet_96568_33628">http://www.oschina.net/code/snippet_96568_33628</a></p><p></p><p>几个主要的文件</p><p>Maven pom.xml</p><p></p><pre name="code" class="html">
 类似资料: