4.0.0
com.test
Test
war
0.0.1
Test
http://maven.apache.org
1.8
1.8
junit
junit
3.8.1
test
org.springframework
spring-aop
4.3.2.RELEASE
org.aspectj
aspectjweaver
1.6.11
jar
compile
cglib
cglib
3.2.4
org.springframework
spring-beans
4.3.2.RELEASE
org.springframework
spring-webmvc
4.3.2.RELEASE
org.springframework
spring-jdbc
4.3.2.RELEASE
org.springframework
spring-web
4.3.2.RELEASE
org.springframework
spring-tx
4.3.2.RELEASE
commons-dbcp
commons-dbcp
1.4
mysql
mysql-connector-java
5.1.18
org.mybatis
mybatis
3.4.2
org.mybatis
mybatis-spring
1.3.0
org.mybatis
mybatis-ehcache
1.0.0
log4j
log4j
1.2.17
com.alibaba
fastjson
1.1.41
org.slf4j
slf4j-api
1.7.7
org.slf4j
slf4j-log4j12
1.7.7
org.codehaus.jackson
jackson-mapper-asl
1.9.13
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
commons-codec
commons-codec
1.9
javax.servlet
javax.servlet-api
3.1.0
org.apache.shiro
shiro-core
1.3.2
org.apache.shiro
shiro-web
1.3.2
org.apache.shiro
shiro-ehcache
1.3.2
org.apache.shiro
shiro-spring
1.3.2
com.google.collections
google-collections
1.0
com.google.guava
guava
19.0
org.projectlombok
lombok
1.16.16
javax.servlet.jsp
jsp-api
2.2
jstl
jstl
1.2
com.fasterxml.jackson.core
jackson-core
2.8.3
org.codehaus.jackson
jackson-core-asl
1.9.13
com.fasterxml.jackson.core
jackson-databind
2.8.3
com.fasterxml.jackson.core
jackson-annotations
2.8.3
org.apache.shiro
shiro-quartz
1.2.2
org.springframework
spring-context-support
3.2.8.RELEASE
net.sf.ehcache
ehcache-core
2.6.11
commons-collections
commons-collections
3.2.1
org.springframework
spring-test
3.2.4.RELEASE
provided
Test
org.mybatis.generator
mybatis-generator-maven-plugin
1.3.2
src/main/resources/generator.xml
true
true
Generate MyBatis Artifacts
generate
org.mybatis.generator
mybatis-generator-core
1.3.2
org.apache.maven.plugins
maven-surefire-plugin
2.19.1
true
org.apache.maven.plugins
maven-resources-plugin
3.0.1
UTF-8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
src/main/resources
**/*
true
dev
true
192.168.*.*:3306/dev_test
src/main/resources/jdbc.properties
src/main/resources/log4j.properties
test
192.168.*.*:3306/creditloan_ph
src/main/resources/jdbc.properties
src/main/resources/log4j.properties
product
192.168.*.*:3306/creditloan_ph
src/main/resources/jdbc.properties
src/main/resources/log4j.properties
classpath:jdbc.properties
classpath:com/loan/dao/xml/*.xml
connection.driverClassName=com.mysql.jdbc.Driver
connection.url=jdbc:mysql://192.168.*.*:3306/dev_test?useUnicode=true&characterEncoding=UTF-8
connection.username=user
connection.password=pwd
connection.initialSize=0
connection.maxActive=100
connection.maxIdle=30
connection.minIdle=5
connection.maxWait=5000
connection.removeAbandoned=true
connection.removeAbandonedTimeout=3000
connection.logAbandoned=false
connection.defaultAutoCommit=true
connection.defaultReadOnly=false
connection.validationQuery=SELECT 1
connection.testOnBorrow=true
log4j.rootLogger=INFO, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.threshold=INFO
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d \u4FE1\u9500\u7F51\u7AD9\u540E\u53F0\u7BA1\u7406 -->%5p{%F:%L}-%m%n
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.threshold=ERROR
log4j.appender.logfile.File=${catalina.home}/logs/Test/Test
log4j.appender.logfile.DatePattern='-'yyyy-MM-dd-HH-mm'.log'
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d \u4FE1\u9500\u7F51\u7AD9\ -->%5p{%F:%L}-%m%n
webAppRootKey
test
log4jConfigLocation
classpath:log4j.properties
org.springframework.web.util.Log4jConfigListener
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
CharacterEncodingFilter
/*
contextConfigLocation
classpath:application-context.xml
classpath:spring-shiro.xml
org.springframework.web.context.ContextLoaderListener
dispatcher
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
dispatcher
/
30
至此,ssm基本配置完成
/static/** = anon
/index = anon
/unauthorized = anon
/login =authc
/logout = logout
/admin/**=user,kickout
/unauthorized
/login
package com.loan.credentials;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.SaltedAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
/**
*
* User: Zhang Kaitao
*
* Date: 14-1-28
*
* Version: 1.0
*/
public class RetryLimitHashedCredentialsMatcher extends
HashedCredentialsMatcher {
//AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。
private Cache passwordRetryCache;
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
}
//控制密码输入错误次数
@Override
public boolean doCredentialsMatch(AuthenticationToken token,
AuthenticationInfo info) {
String username = (String) token.getPrincipal();
// retry count + 1
AtomicInteger retryCount = passwordRetryCache.get(username);
System.out.println("retryCount:"+retryCount);
if (retryCount == null) {
retryCount = new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if (retryCount.incrementAndGet() > 5) {
// if retry count > 5 throw
throw new ExcessiveAttemptsException();
}
boolean matches = super.doCredentialsMatch(token, info);
if (matches) {
// clear retry count
passwordRetryCache.remove(username);
}
return matches;
}
}
package com.loan.realm;
import org.apache.log4j.Logger;
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.util.ByteSource;
import com.loan.entity.User;
import com.loan.pojo.UserParams;
import com.loan.service.ResourceService;
import com.loan.service.RoleService;
import com.loan.service.UserRoleService;
import com.loan.service.UserService;
/**
* @ClassName: UserRealm
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月5日 上午10:09:51
*
*/
public class UserRealm extends AuthorizingRealm {
private static final Logger logger = Logger.getLogger(UserRealm.class);
@javax.annotation.Resource
private UserRoleService userRoleService;
@javax.annotation.Resource
private ResourceService resourceService;
@javax.annotation.Resource
private UserService userService;
@javax.annotation.Resource
private RoleService roleService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//直接调用getPrimaryPrincipal得到之前传入的用户名
User user = (User) principals.getPrimaryPrincipal();
logger.info("[用户:" + user.getUsername() + "|权限授权]");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//根据用户名调用UserService接口获取角色及权限信息
authorizationInfo.setRoles(roleService
.loadRoleIdByUsername(user.getUsername()));
authorizationInfo.setStringPermissions(resourceService
.loadPermissionsByUsername(user.getUsername()));
logger.info("[用户:" + user.getUsername() + "|权限授权完成]");
return authorizationInfo;
}
@Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
// 获取基于用户名和密码的令牌
// 实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = (String) token.getPrincipal();
System.out.println("pwd:"+token.getCredentials().toString());
logger.info("[用户:" + username + "|系统权限认证]");
User u = new User();
u.setUsername(username);
if (userService.find(new UserParams(u)).size() > 0) {
User sqluser = userService.find(new UserParams(u)).get(0);
// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
System.out.println("Realm:"+ByteSource.Util.bytes(sqluser.getCredentialsSalt()));
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sqluser, sqluser.getPassword(),
ByteSource.Util.bytes(sqluser.getCredentialsSalt()), this.getName());// realm
logger.info("[用户:" + username + "|系统权限认证完成]");
return authenticationInfo;
}
return null;
}
}
package com.loan.util;
import java.util.Date;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
public class MySessionListener1 implements SessionListener {
@Override
public void onStart(Session session) {//会话创建时触发
System.out.println("会话创建:" + session.getId()+"》》时间:"+session.getLastAccessTime());
}
@Override
public void onExpiration(Session session) {//会话过期时触发
System.out.println("会话过期:" + session.getId()+"》》时间:"+new Date());
}
@Override
public void onStop(Session session) {//退出/会话过期时触发
System.out.println("会话停止:" + session.getId()+"》》时间:"+session.getLastAccessTime());
}
}
package com.loan.util;
import java.io.Serializable;
import java.util.Deque;
import java.util.LinkedList;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import com.loan.entity.User;
public class KickoutSessionControlFilter extends AccessControlFilter{
private String kickoutUrl; //踢出后到的地址
private boolean kickoutAfter; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
private int maxSession; //同一个帐号最大会话数 默认1
private SessionManager sessionManager;
private Cache> cache;
public void setKickoutUrl(String kickoutUrl) {
this.kickoutUrl = kickoutUrl;
}
public void setKickoutAfter(boolean kickoutAfter) {
this.kickoutAfter = kickoutAfter;
}
public void setMaxSession(int maxSession) {
this.maxSession = maxSession;
}
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
public void setCacheManager(CacheManager cacheManager) {
this.cache = cacheManager.getCache("shiro-activeSessionCache");
}
/**
* 是否允许访问,返回true表示允许
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
return false;
}
/**
* 表示访问拒绝时是否自己处理,如果返回true表示自己不处理且继续拦截器链执行,返回false表示自己已经处理了(比如重定向到另一个页面)。
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
if(!subject.isAuthenticated() && !subject.isRemembered()) {
//如果没有登录,直接进行之后的流程
return true;
}
Session session = subject.getSession();
String username = ((User)(subject.getPrincipal())).getUsername();
Serializable sessionId = session.getId();
// 初始化用户的队列放到缓存里
Deque deque = cache.get(username);
if(deque == null) {
deque = new LinkedList();
cache.put(username, deque);
}
//如果队列里没有此sessionId,且用户没有被踢出;放入队列
if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
deque.push(sessionId);
}
//如果队列里的sessionId数超出最大会话数,开始踢人
while(deque.size() > maxSession) {
Serializable kickoutSessionId = null;
if(kickoutAfter) { //如果踢出后者
kickoutSessionId=deque.getFirst();
kickoutSessionId = deque.removeFirst();
} else { //否则踢出前者
kickoutSessionId = deque.removeLast();
}
try {
Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
if(kickoutSession != null) {
//设置会话的kickout属性表示踢出了
kickoutSession.setAttribute("kickout", true);
}
} catch (Exception e) {//ignore exception
e.printStackTrace();
}
}
//如果被踢出了,直接退出,重定向到踢出后的地址
if (session.getAttribute("kickout") != null) {
//会话被踢出了
try {
subject.logout();
} catch (Exception e) {
}
WebUtils.issueRedirect(request, response, kickoutUrl);
return false;
}
return true;
}
}
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
package com.loan.entity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
/**
* @ClassName: User
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月5日 下午2:31:58
*
*/
@SuppressWarnings("serial")
@Data
public class User implements Serializable {
private Long id;
private String username;// 用户名
private String workNo;// 工作编号
private String salt;// 盐(密码安全)
private String password;// 密码
private Integer age;// 年龄
private String state;// 状态
private Long orgId;
private String pic;
private String phone;
private String address;
private String email;
private Integer percent;
/**
* @Title: getCredentialsSalt
* @Description: salt = salt + username
* @param @return 设定文件
* @return String 返回类型
* @author jiayq
* @throws
*/
public String getCredentialsSalt() {
return username + salt;
}
}
insert into sys_user(id,username,work_no,salt,password,age,state,org_id,pic,phone,address,email,percent) values (#{id},#{username},#{workNo},#{salt},#{password},#{age},#{state},#{orgId},#{pic},#{phone},#{address},#{email},#{percent})
package com.loan.dao.mapper;
import java.util.List;
import com.loan.entity.User;
import com.loan.pojo.UserParams;
/**
* @ClassName: UserMapper
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月29日 下午4:08:43
*
*/
public interface UserMapper {
public void save(User user);
}
package com.loan.service;
import java.util.List;
import com.loan.entity.User;
/**
* @ClassName: UserService
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月7日 上午10:09:32
*
*/
public interface UserService {
public void save(User user);
}
package com.loan.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.loan.dao.mapper.UserMapper;
import com.loan.dao.mapper.UserRoleMapper;
import com.loan.entity.User;
import com.loan.pojo.UserParams;
import com.loan.service.UserService;
import com.loan.util.EndecryptUtils;
import com.loan.util.PasswordHelper;
/**
* @ClassName: UserServiceImpl
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月6日 上午9:24:49
*
*/
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private UserRoleMapper userRoleMapper;
@Override
public void save(User user) {
User u=new PasswordHelper().encryptPassword(user);
userMapper.save(u);
}
}
package com.loan.util;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import com.loan.entity.User;
public class PasswordHelper {
private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
private String algorithmName = "md5";
private final int hashIterations = 2;
public User encryptPassword(User user) {
if(user.getSalt()==null||("").equals(user.getSalt())){
user.setSalt(randomNumberGenerator.nextBytes().toHex());
}
String newPassword = new SimpleHash(algorithmName, user.getPassword(),
ByteSource.Util.bytes(user.getCredentialsSalt()), hashIterations).toHex();
user.setPassword(newPassword);
return user;
}
}
package com.loan.controller;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.loan.entity.User;
import com.loan.service.UserService;
@Controller
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/application-context.xml")
@RequestMapping("/test")
public class TestController {
@Resource
private UserService userService;
@Test
public void userCreate(){
User user=new User();
user.setAge(20);
user.setPassword("123");
user.setUsername("shiroUser");
userService.save(user);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
登录
package com.loan.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.loan.entity.User;
import com.loan.service.UserService;
/**
* @ClassName: LoginController
* @Description: TODO(登录controller)
* @author jiayq
* @date 2016年9月5日 下午5:06:33
*
*/
@Controller
@RequestMapping("/")
public class LoginController {
@Resource
private UserService userService;
/**
* @Title: loginView
* @Description: TODO(转向登录界面)
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
@RequestMapping(value = "/login")
public String loginView(){
return "login";
}
/**
* @Title: login1
* @Description: TODO(shiro+EndecryptUtils进行认证)
* @param @param request
* @param @param model
* @param @param username
* @param @param password
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
@RequestMapping(value = "/loginTest")
public String login(HttpServletRequest request, Model model, String username, String password,boolean rememberMe) {
System.out.println("rememberMe:"+rememberMe);
//将form中的用户名密码传入Realm 的doGetAuthenticationInfo
UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());
token.setRememberMe(rememberMe);
Subject currentUser = SecurityUtils.getSubject();
String error = "";
try {
currentUser.login(token);
} catch (UnknownAccountException ex) {// 用户名没有找到
error = "您输入的用户名不存在!";
} catch (IncorrectCredentialsException ex) {// 用户名密码不匹配
error = "用户名密码不匹配 !";
}
catch(ExcessiveAttemptsException e){
error="密码错误次数已超五次,账号锁定1小时!";
}
catch (AuthenticationException ex) {// 其他的登录错误
ex.printStackTrace();
error = "其他的登录错误 !";
}
// 验证是否成功登录的方法
if (currentUser.isAuthenticated()) {
return "redirect:/admin/index";
} else {
model.addAttribute("message", error);
currentUser.logout();
return "login";
}
}
}
重点逻辑:
package com.loan.entity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
/**
* @ClassName: User
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月5日 下午2:31:58
*
*/
@SuppressWarnings("serial")
@Data
public class User implements Serializable {
private Long id;
private String username;// 用户名
private String workNo;// 工作编号
private String salt;// 盐(密码安全)
private String password;// 密码
private Integer age;// 年龄
private String state;// 状态
private Long orgId;
private String pic;
private String phone;
private String address;
private String email;
private Integer percent;
/**
* @Title: getCredentialsSalt
* @Description: salt = salt + username
* @param @return 设定文件
* @return String 返回类型
* @author jiayq
* @throws
*/
public String getCredentialsSalt() {
return username + salt;
}
}
package com.loan.entity;
import java.io.Serializable;
import lombok.Data;
/**
* @ClassName: UserRole
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月20日 上午10:17:50
*
*/
@SuppressWarnings("serial")
@Data
public class UserRole implements Serializable {
private Long id;
private Long roleId;//角色id
private Long userId;//用户id
}
package com.loan.entity;
import java.io.Serializable;
import lombok.Data;
/**
* @ClassName: Role
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月20日 上午10:15:29
*
*/
@SuppressWarnings("serial")
@Data
public class Role implements Serializable{
private Long id;
private String name;//名称
private String description;//描述
private String state;//状态
private String code;//编码
private Long pid ;//父id
private String remark;//备注
//关联资源列表
private String resources;
}
package com.loan.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
* @ClassName: Resource
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月19日 下午4:57:11
*
*/
@SuppressWarnings("serial")
@Data
public class Resource implements Serializable{
private Long id;
private String name;//名称
//private ResourceType type = ResourceType.menu;//资源类型
private String type;
private Integer leaf;//0表示是叶子节点
private Long priority;//顺序
private Long pid;//父id
private String permission;//权限
private String status;//状态
private String url;//路径
private String outUrl;//站外路径
private String pic;
//关联的角色列表
private List roles;
private List children = new ArrayList();
}
package com.loan.entity;
import java.io.Serializable;
import lombok.Data;
/**
* @ClassName: RoleResource
* @Description: TODO(这里用一句话描述这个类的作用)
* @author jiayq
* @date 2016年9月20日 上午10:16:57
*
*/
@Data
public class RoleResource implements Serializable{
private Long id;
private Long roleId;//角色id
private Long resourceId;//资源id
}
@Test
public void resourceCreate(){
//建立三个资源
for(int i=1;i<4;i++){
com.loan.entity.Resource resource=new com.loan.entity.Resource();
resource.setName("resourceTest_"+i);
resource.setPermission("test:permission_"+i);
resourceService.save(resource);
}
}
(2)新建role
@Test
public void roleCreate(){
Role role=new Role();
role.setName("testRole");
roleService.save(role);
for(int i=143;i<146;i++){
RoleResource roleResource=new RoleResource();
roleResource.setRoleId(role.getId());
roleResource.setResourceId((long)i);
roleResourceService.save(roleResource);
}
}
(3)新建user
@Test
public void UserCreate(){
User user=new User();
user.setAge(20);
user.setPassword("123");
user.setUsername("shiroUser1");
userService.save(user);
UserRole ur=new UserRole();
ur.setRoleId((long)25);
ur.setUserId(user.getId());
userRoleService.save(ur);
}
至此,所以关系逻辑建立。
3、UserRealm权限授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//直接调用getPrimaryPrincipal得到之前传入的用户名
User user = (User) principals.getPrimaryPrincipal();
logger.info("[用户:" + user.getUsername() + "|权限授权]");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//根据用户名调用UserService接口获取角色及权限信息
authorizationInfo.setRoles(roleService
.loadRoleIdByUsername(user.getUsername()));
authorizationInfo.setStringPermissions(resourceService
.loadPermissionsByUsername(user.getUsername()));
logger.info("[用户:" + user.getUsername() + "|权限授权完成]");
return authorizationInfo;
}
roleMapper.xml
resourceMapper.xml
3、通过jsp/注释测试
(1)jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
test
欢迎游客访问,登录
欢迎 登录,退出
用户[ ]已身份验证通过
用户[ ]拥有testRole角色
用户[ ]拥有权限test:permission_1
登录结果:
(2)通过注解控制方法的访问:
@RequiresPermissions("test:permission_1")
@RequestMapping("/testAnnotation")
public String testAnnotation(){
return "/index";
}
@RequiresPermissions("test:nopermission")
@RequestMapping("/testAnnotation1")
public String testAnnotation1(){
return "index";
}
测试结果:
终于完了!!!
源代码下载:http://download.csdn.net/download/dreamer_8399/9959021