On this page
Apache Shiro Basics
Apache Shiro is a lightweight Java security framework providing authentication, authorization, session management, and cryptography. It is simpler than Spring Security and works outside the Spring ecosystem.
Core Concepts
| Concept | Description |
|---|---|
| Subject | Current user (thread-bound) |
| SecurityManager | Central coordinator |
| Realm | Bridge to user data (DB, LDAP) |
| Session | User session management |
| Filter | Request-level security |
Maven Dependency
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.13.0</version>
</dependency>
INI Configuration
shiro.ini:
[main]
authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter
roles = org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
[users]
admin = secret, admin
alice = password, user
[roles]
admin = *
user = order:read, order:create
[urls]
/login = authc
/logout = logout
/admin/** = roles[admin]
/api/** = authc
Programmatic Authentication
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken("alice", "password");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException | IncorrectCredentialsException e) {
// handle failed login
}
}
// Check permissions
if (currentUser.isPermitted("order:create")) {
createOrder();
}
currentUser.logout();
Custom Realm
public class DatabaseRealm extends AuthorizingRealm {
private final UserRepository userRepository;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
String email = (String) token.getPrincipal();
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new UnknownAccountException("Unknown user: " + email));
return new SimpleAuthenticationInfo(email, user.getPasswordHash(), getName());
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String email = (String) principals.getPrimaryPrincipal();
User user = userRepository.findByEmail(email).orElseThrow();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(user.getRoles());
info.setStringPermissions(user.getPermissions());
return info;
}
}
Spring Boot Integration
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.13.0</version>
</dependency>
@Bean
public Realm realm() {
return new DatabaseRealm(userRepository);
}
Shiro vs Spring Security
| Feature | Shiro | Spring Security |
|---|---|---|
| Complexity | Lower | Higher |
| Spring integration | Good | Native |
| OAuth2/OIDC | Limited | Full support |
| Ecosystem | Smaller | Large |
| Best for | Simple apps, non-Spring | Enterprise Spring apps |
Best Practices
- Use BCrypt or similar for password hashing in custom Realms
- Keep Realm logic focused on data access — no business rules
- Use permission strings (
resource:action) for fine-grained control - Prefer Spring Security for new Spring Boot projects with OAuth2 needs
- Enable session timeout and concurrent session control in production