EasyShiro(最后有例子下载)
特色
1/简单易用2/轻装上阵3/ 保留session功能并兼顾性能4/兼容session、jwt和单纯的token访问5/提供SessionUtils工具 应用
1/加入依赖2/写一个MyAuthenticationInfoService的实现,这里只是为了演示,直接将帐户权限数据放在accounts变量里,实际应用时一般来自数据库3/写一个controller接受登录和授权测试4/在application启动类加入"com.freestyle.easyshiro.web"的扫描 postman测试cache对于shiro的重要性例子下载
特色 1/简单易用几乎开箱即用,不用写冗余繁琐的代码。
登录后储存在Principal的为内置的UserDtoWithPermission,它是AuthenticationWithPermission的实现,包含如下信息:
account/roles/permissions
没有集成数据库,AbstractAccountRealm留有接口可以自行实现login(身份认证)和getAuthorization(获取授权),所以你可以用mysql,postgresql或memory任何一种方式来管理帐户、授权认证
3/ 保留session功能并兼顾性能重写session dao,后端用J2Cache实现,并对其加入了增强的jackson序列化功能,j2cache的序列化配置默认用jackson,这个才能更好应对shiro的session在redis的存取。而由于用了j2Cache(一级缓存用caffeine,二级缓存用redis),默认通知机制用了rabbitmq,具体配置请查阅包内j2cache.properties。所以你也可以通过自行配置j2cache.properties和caffeine.properties来进行更细节的参数调整
easyshiro保留session管理,并用j2cache进行缓存,兼容jwt token和session token,具体能数配置放在easy-shiro.yml
easy-shiro:
session-time-out: 1800
cache-enabled: true
allow-cross-domain: true
sessionIdUrlRewritingEnabled: false
#如果配置sessionTokenName,则会从request的header的#sessionTokenName里面取这个token从而可以不用传递cookie
session-token-name: token
#如果配置jwtTokenName,则会从request的header的#jwtTokenName里面取jwt令牌并验证其有效性并从中取出token
#优先顺序: cookie->session token -> jwt token
jwt-token-name: access-token
session-region: my-easy-shiro-web-sample
redirect:
"login": "/user/login"
"401": "/user/login"
4/兼容session、jwt和单纯的token访问
因为eashshiro用j2cache管理session,所以性能不是问题, 通过配置easy-shiro.yml登录后自行返回jwt token和token,之后的访问携带三者任何一样作为鉴权依据即可。
5/提供SessionUtils工具可直接根据sessionid拿到Subject,便于在非web容器的应用(如netty或其他iot环境)进行认证和鉴权
Serializable sessionId=getSessionIdFrom ...
SessionUtils sessionUtils=new SessionUtils(shiroConfig.getSecurityManager(),
(DefaultSessionManager) ((DefaultSecurityManager)shiroConfig.getSecurityManager()).getSessionManager());
Subject subject=sessionUtils.createSubject(sessionId);
Assert.assertNotNull(subject);
subject.checkPermission("P3"); //检查授权
...
应用
基本上开箱即用,包里默认自带filter-chain-map.json,如果你有需要就在自己的项目里面新建一个覆盖它:
{
"/user/login": "anon",
"/swagger-ui.html": "anon",
"/swagger-resources/**": "anon",
"/v2/api-docs": "anon",
"/css/**": "anon",
"/js/**": "anon",
"/fonts/**": "anon",
"/img/**": "anon",
"/**": "myauthc,crossDomain"
}
easyshiro默认用到rabbitmq和redis,它们的默认配置如下,如果有需要修改的请覆盖j2cache.properties
# RabbitMQ properties rabbitmq.exchange = j2cache rabbitmq.host = localhost rabbitmq.port = 5672 rabbitmq.username = root rabbitmq.password = 123456 rabbitmq.virtualHost = / redis.hosts = 127.0.0.1:6379 redis.timeout = 2000 redis.password =12345678 redis.database = 0 redis.ssl = false1/加入依赖
2/写一个MyAuthenticationInfoService的实现,这里只是为了演示,直接将帐户权限数据放在accounts变量里,实际应用时一般来自数据库sonatype-nexus-snapshots Sonatype Nexus Snapshots https://s01.oss.sonatype.org/content/repositories/snapshots/ false true io.github.tiger822 easy-shiro-web 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aop org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
@Service
public class MyAuthenticationInfoServiceImpl implements MyAuthenticationInfoService {
private Map accounts=new HashMap<>();
public MyAuthenticationInfoServiceImpl() {
accounts.put("user1",new MyAuthenticationInfo(new UserDtoWithPermission("user1",new HashSet(){{add("ROLE1");add("ROLE2");}},
new HashSet(){{add("P1");}}),"123456","accountRealm"));
accounts.put("user2",new MyAuthenticationInfo(new UserDtoWithPermission("user2",new HashSet(){{add("ROLE1");add("ROLE2");}},
new HashSet(){{add("P1");add("P2");}}),"123456","accountRealm"));
}
@Override
public MyAuthenticationInfo login(UsernamePasswordToken token) {
return accounts.get(token.getUsername());
}
@Override
public AuthorizationInfo getAuthorization(UserDtoWithPermission principal) {
return principal;
}
}
3/写一个controller接受登录和授权测试
@RestController
@RequestMapping("/user")
public class LoginController {
@Resource
private WebSessionEasyShiroProperties properties;
@Resource
private WebSessionAbleEasyShiroConfig shiroConfig;
@GetMapping("login")
public Object login(@RequestParam(value = "user",required = false)String user, @RequestParam(value = "password",required = false) String password, HttpServletResponse response){
if (user==null){
return "显示登录界面";
}
Subject subject = SecurityUtils.getSubject(); // 获取当前主体
UsernamePasswordToken token = new UsernamePasswordToken(user, password);
try {
subject.login(token); // 登录
if (!StringUtils.isBlank(properties.getSessionTokenName())){
response.setHeader(properties.getSessionTokenName(), subject.getSession().getId().toString());
}
if (!StringUtils.isBlank(properties.getJwtTokenName())){
String jwtToken= JwtUtils.getToken(subject.getSession().getId(),properties.getSessionTimeOut(), TimeUnit.SECONDS);
//返回两组token,之后的访问随便用哪个
response.setHeader(properties.getJwtTokenName(), jwtToken);
}
return ResponseEntity.fromResult(0,"OK");
}
catch (UnknownAccountException |IncorrectCredentialsException e){
return ResponseEntity.fromErr(0,-1,"用户或密码无效");
}
}
@GetMapping("subject")
@RequiresPermissions(logical = Logical.AND, value = {"p1"})
public Object getSubject(HttpServletRequest request) throws JsonProcessingException {
Subject subject=shiroConfig.getSessionUtils().createSubject(request.getHeader("token"));
UserDtoWithPermission userDtoWithPermission=(UserDtoWithPermission)subject.getPrincipal();
Map values=new HashMap<>();
values.put("account",userDtoWithPermission.getAccount() );
values.put("roles",userDtoWithPermission.getRoles());
values.put("permissions",userDtoWithPermission.getPermissions());
return ResponseEntity.fromResult(0,values);
}
@GetMapping("p1")
@RequiresPermissions(logical = Logical.AND, value = {"p1"})
public Object p1(){
return ResponseEntity.fromResult(0,"权限通过,返回P1");
}
@GetMapping("p2")
@RequiresPermissions(logical = Logical.AND, value = {"p2"})
public Object p2(){
return ResponseEntity.fromResult(0,"权限通过,返回P2");
}
}
4/在application启动类加入"com.freestyle.easyshiro.web"的扫描
@SpringBootApplication(scanbasePackages = {"com.freestyle.easyshiro","com.freestyle.easyshiro.web"})
@EnableAspectJAutoProxy(proxyTargetClass=true,exposeProxy = true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
postman测试
get http://localhost:8080/user/login?user=user1&password=123456
返回结果除了cookie还返回了access-token和token。登录后,redis后台便有了session数据,只要不同的服务同样用了easyshiro这套鉴权工具,后面的请求随便用哪个作为令牌对任何一组服务进行访问即可。
通过携带cookie进行访问:
通过携带token进行访问:
通过携带jwt的access token进行访问:
shiro对session的访问次数一点也不严谨,一次请求中它会频繁访问session(19次读,1次更新),如下图,所以1级缓冲用上高性能的caffeine最好不过了,命中率非常高,而2级缓存用redis,则可满足一处登录到处使用的需求。
09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.990 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - update session ,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.991 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - storeSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.995 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.995 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.996 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.996 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.996 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.997 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.997 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f 09:33:02.999 [http-nio-8080-exec-7] DEBUG com.freestyle.easyshiro.web.J2CacheSessionDAO - doReadSession,session id:7714603b-2ed1-4b2f-a804-2f0178ad4e2f例子下载
https://download.csdn.net/download/rocklee/84986491



